Como faço para substituir caracteres apenas em certas linhas?

5

Eu preciso substituir aspas simples por aspas duplas e aspas duplas por aspas simples em mais de 600 arquivos. Eu tenho lido vários tópicos a maior parte do dia. Eu sou dificultado por conhecer apenas alguns comandos básicos de script de shell e uma falta de familiaridade com o regexp.

Abaixo está um arquivo de exemplo que fiz um pouco genérico.

   some text KEYWORD_1 table name column = "string" AND column = "string"
    Additional text
          .
          .
          .
   some text KEYWORD_2 text 'text in quote' etc. 

Eu só quero alterar as aspas nas duas linhas com KEYWORDs. Não posso garantir que as palavras-chave sejam sempre de primeira linha e última linha. Eu preciso da minha solução para encontrar a palavra-chave e alterar todas as citações nessa linha apenas.

Eu tentei algumas coisas que encontrei em perguntas similares neste fórum, incluindo uma meta no SED. Eu tentei descobrir como usar este comando: sed -i 's/foo\(.*baz\)/bar/' file . De acordo com esse tópico, o comando "Substitui foo por bar apenas se houver um baz mais tarde na mesma linha". Minha palavra-chave não está mais na mesma linha no começo e eu não consegui fazer isso funcionar para mim.

Eu também tentei ex -sc 'g/DEL/s/ALF/BRA/g' -cx file que não fez nada. Eu estou supondo que não pode ser executado a partir da linha de comando. Eu realmente não quero abrir cada um dos 600 arquivos.

Em um determinado momento, tentei grep KEYWORD_1 file | sed -i "s/'/\"/g" file
Claro, isso mudou todas as citações no arquivo e não apenas a linha.

Aposto que a solução é simples e não consigo ver. Como posso fazer isso?

Conforme solicitado, minha saída desejada é:

some text KEYWORD_1 table name column = 'string' AND column = 'string'
    Additional text
          . 
          .
          .
some text KEYWORD_2 text "text in quote" etc.
    
por Emily Shaffer 13.01.2017 / 23:37

3 respostas

3

A complicação aqui é que, se você substituir todos os ' por " e, em seguida, todos os " por ' , você terá apenas ' . Então, primeiro você precisará substituir ' por outra coisa - por exemplo, o caractere NULL ( " ), que você pode seguramente assumir, não estará em seu arquivo de entrada - então ' with " e substitua essa outra coisa por -pe novamente. Por exemplo, em perl:

$ perl -pe "if(/KEYWORD){s/'/
perl -pe "tr/'\"/\"'/ if /^KEYWORD/" file
/g; s/\"/'/g; s/
$ perl -pe "if(/KEYWORD){s/'/
perl -pe "tr/'\"/\"'/ if /^KEYWORD/" file
/g; s/\"/'/g; s/%pre%/\"/g}" file KEYWORD_1 table name column = 'string' AND column = 'string' Additional text . . . KEYWORD_2 text "text in quote" etc.
/\"/g}" file KEYWORD_1 table name column = 'string' AND column = 'string' Additional text . . . KEYWORD_2 text "text in quote" etc.

Explicação

  • -e : p digite cada linha de entrada depois de aplicar o script fornecido por if(/KEYWORD/){something} .
  • something : do KEYWORD apenas se essa linha corresponder a s/foo/bar/g .
  • foo : substitua todas as ocorrências de bar na linha por g . O \" significa "global". Sem isso, apenas a primeira ocorrência em cada linha seria substituída.

Observe que, como o próprio script está entre aspas duplas, as aspas duplas dentro do script precisam ser escapadas ( tr ).

Como apontado nos comentários, há uma maneira mais direta que eu deveria ter pensado em primeiro lugar:

%pre%

O operador tr/searchlist/replacementlist/ traduz as listas de caracteres. O formato geral é ' . Portanto, isso substituirá todos os " por " e todos os ' por KEYWORD apenas nas linhas correspondentes a %code% .

    
por 13.01.2017 / 23:50
6

Alterando caracteres

Alterar um conjunto de caracteres para outro conjunto de caracteres geralmente é uma tarefa para o comando tr , mas como você deseja fazê-lo somente em determinadas linhas, será melhor realizado por sed , que possui y comando semelhante a tr :

sed -e "/^KEYWORD_1/  y/\"/'/" \
    -e "/^KEYWORD_2/  y/'/\"/" \
    file

Cada comando sed aqui começa com um seletor de linha /^KEYWORD/ que instrui sed a operar somente na linha que corresponde ao padrão entre / . Aqui, os padrões começam com o caractere ^ para indicar que eles devem ser encontrados no início da linha.

Após o seletor de linha, o comando de substituição sed y/set1/set2/g substitui todas as ocorrências de um caractere em set1 pelo caractere que tem a mesma posição em set2 .

Troca de caracteres

Agora, se na mesma linha você quiser substituir cada " por ' e, ao mesmo tempo, cada ' com " , você poderá usar apenas um comando:

sed -e "/^KEYWORD_1\|^KEYWORD_2/  y/\"'/'\"/" file
    
por 13.01.2017 / 23:49
0

Ligeiramente bruto, mas funcionando GNU awk:

$ awk -v sq="'" '/KEYWORD/{if ($0~sq){ gsub(sq,"\"")} else if ($0~"\"") gsub(/\"/,sq)};1' input.txt                      
KEYWORD_1 table name column = 'string' AND column = 'string'
Additional text
      .
      .
      .
KEYWORD_2 text "text in quote" etc.

A variável sq é usada para representar aspas simples, já que incorporá-las no próprio bloco de código é um pouco trabalhoso no awk. A ideia básica é que procuramos por padrão, se o padrão for encontrado - tomamos a decisão sobre o que substituir. Final 1 simplesmente diz ao awk para imprimir as linhas.

Quanto à saída do arquivo, simplesmente use o operador > do shell para redirecionar o texto para o arquivo temporário e substitua o arquivo antigo pelo novo comando via mv .

    
por 14.01.2017 / 10:15