Substituir uma string antes de uma certa linha

6

Eu tenho um arquivo como:

ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0  COMPRESS 0 ,
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR ,
PRIMARY INDEX ( CALENDAR_DATE );

Eu quero substituir o ',' por ')' na linha imediatamente antes da linha contendo PRIMARY.

O resultado deve ser:

ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0  COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
    
por Mike 04.09.2018 / 16:22

5 respostas

9

Usando GNU sed :

sed  'N;s/,\(\s*\n.*PRIMARY\)/)/;P;D' file

ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0  COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );
  • N Lê / acrescenta a próxima linha de entrada no espaço padrão.
  • P Imprime até a primeira nova linha incorporada do espaço de padrão atual.
  • D Excluir até a primeira nova linha incorporada no espaço padrão. Inicie o próximo ciclo, mas pule a leitura da entrada se ainda houver dados no espaço de padrão.
por 04.09.2018 / 16:56
8

Tente reverter o arquivo, fazendo a substituição da sequência na linha após PRIMARY e, em seguida, revertendo novamente o arquivo:

tac file | sed '/PRIMARY/ {n; s/,$/)/}' | tac
    
por 04.09.2018 / 16:49
7

tente isso,

perl -0777 -pe 's/,([^\n,]*\n[^\n]*PRIMARY)/)$1/g'

Isso substituirá o último , por ) nas linhas antes de qualquer linha, incluindo PRIMARY .

Explicação

  • perl -0777 slurp arquivo inteiro (leia como uma linha)
  • s/search_pattern/replacement/g Substituir padrão de pesquisa por substituição global
por 04.09.2018 / 16:32
5

Se você usar ed em vez de sed , poderá usar um endereço regex com deslocamento negativo:

g/PRIMARY/-1 s/,$/)/

Ex.

$ printf 'g/PRIMARY/-1 s/,$/)/\n,p\nq\n' | ed -s file
ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0  COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );

ou (para edição no local)

printf 'g/PRIMARY/-1 s/,$/)/\nwq\n' | ed -s file

A substituição corresponderá a TODAS as instâncias de /PRIMARY/ - se você quiser substituir apenas a primeira, remova o modificador g .

    
por 04.09.2018 / 17:36
2

Com POSIX - ly sed , você pode fazer o seguinte:

sed -e '
    /PRIMARY/!{x;1!p;d;}
    x;s/,/)/;$G
' input-file.txt

Saída:

ID_SOUR_CALENDAR BIGINT NOT NULL DEFAULT 0  COMPRESS 0 )
UNIQUE PRIMARY INDEX ( CALENDAR_DATE );
ID ,
ID_SOUR )
PRIMARY INDEX ( CALENDAR_DATE );

Trabalhando:

  • Para linhas não PRIMÁRIAS, salvamos a linha e imprimimos a que salvamos no porão.
  • E para o PRIMARY, recuperamos o anterior e efetuamos a transformação.
por 05.09.2018 / 10:02