Como criar um comando bash que crie saída que imite exatamente um arquivo de texto de origem que possa ser colado no shell bash em que histexpand está ativado?

4

O objetivo é criar um comando bash one line que possa ser copiado e colado - por exemplo, publicado em um fórum da web - e depois corrigir os arquivos. Veja como uma maneira de distribuir um arquivo de patch copiando e colando-o na linha de comando.

No sistema de origem:

  1. um arquivo de patch é usado como entrada,
  2. e outro comando bash deve ser usado para criar a saída.

Atualmente isso é feito por meio de:

$ oldifs=$IFS;printf '\n{ ';while IFS= read -r p;do printf 'echo %q; ' "$p";done < custom.patch;printf ' }\n\n';IFS=$oldifs

Isso cria uma saída como:

{ 
...
echo \ //=\ require\ xyz.js; 
echo @@\ -81\,7\ +80\,6\ @@; 
echo $' \t\t\tchild.currentlyBackingUp = $(\'.dashboard-currently-backing-up\', element).dashboardBackup({type: this.type});'; 
...
 }

Isso pode ser usado como entrada em um comando de correção de uma linha no sistema de destino, como:

patch < { echo \ //=\ require\ xyz.js; echo @@\ -81\,7\ +80\,6\ @@; ... }

Até aí tudo bem, até que o arquivo de patch de origem contenha um caractere de estrondo ( ! ). Em seguida, o printf cria uma saída com escape como:

echo $' \t\t\tif (!cp.user.isMyUserQueryLimited()) {'; 
echo $'-\t\t\t\tif (ui.tab.name === "map-tab" && !serverEnv.queryLimited) {'; 
echo $' \t\t\t\tif (!hosted) {';

Ao colar essa linha em uma linha de comando bash, isso resulta em:

#-bash: !cp.user.isMyUserQueryLimited: event not found

Como criar programaticamente dados de fluxo de texto usando um comando bash que pode ser copiado e colado, que gera um fluxo de dados de texto, por um comando que pode ser colado em outro prompt de comando bash onde o histórico expansão está ativada (histexpand = on)?

    
por Pro Backup 21.11.2013 / 16:49

1 resposta

1

Estou um pouco confuso com alguns detalhes da sua pergunta. Em particular, não entendo porque você está gerando instruções echo. Então, talvez eu esteja entendendo mal de você, mas parece que você está procurando uma maneira de aplicar um patch por meio de um comando de copiar e colar. Em caso afirmativo, você pode fazer isso usando heredocs .

Usando sua notação, acho que seria algo assim:

patch <<HEREDOC
...
 //= require xyz.js
@@ -81,7 +80,6 @@
            child.currentlyBackingUp = $('.dashboard-currently-backing-up', element).dashboardBackup({type: this.type});
...
HEREDOC

Aqui está um exemplo simples para ilustrar a técnica.

Primeiro, crie um arquivo:

cat <<HEREDOC > file-v1.txt
this is the first line
HEREDOC

Agora crie uma versão atualizada do arquivo (por exemplo, adicionar uma linha):

cat <<HEREDOC > file-v2.txt
this is the first line
here is a second line
HEREDOC

Agora calcule o patch para os dois arquivos:

diff -u file-v1.txt file-v2.txt

A saída deve ficar assim:

--- file-v1.txt 2017-10-26 09:53:58.000000000 -0500
+++ file-v2.txt 2017-10-26 09:53:58.000000000 -0500
@@ -1 +1,2 @@
 this is the first line
+here is a second line

Agora, aqui está o seu comando:

patch file-v1.txt <<HEREDOC
--- file-v1.txt 2017-10-26 09:53:58.000000000 -0500
+++ file-v2.txt 2017-10-26 09:53:58.000000000 -0500
@@ -1 +1,2 @@
 this is the first line
+here is a second line
HEREDOC

Você deve copiar e colar este comando em seu terminal e executá-lo. Ele atualizará file-v1.txt para conter o texto de file-v2.txt , desde que você esteja no diretório correto.

Além disso, o heredoc não executará a expansão do histórico, como você pode verificar:

cat <<HEREDOC
!!
HEREDOC
    
por 26.10.2017 / 22:00