sed com vários comandos, posso usar o sinalizador w (write)?

1

Aqui estou aprendendo sed, aqui está com vários comandos:

(user@host)-(18:27:39)-(~/Bash_Programming)
$sed '4 { s/fox/elephant/; s/dog/cat/ }' catAndDog.txt 
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown elephant jumps over the lazy cat
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog

Mas onde coloco o sinalizador de substituição w se estou usando vários comandos e quero que os resultados sejam gravados em um arquivo?

w file = write the result of the substitution to a file

EDITAR:

Eu quero escrever toda a saída para o arquivo, uma cópia do original com as alterações feitas.

    
por somethingSomething 06.09.2018 / 20:19

3 respostas

2

Na verdade, existem dois w elementos. Um é um comando, o outro é um sinalizador s/// .

Ambos são usados para escrever o espaço padrão atual em um arquivo.

comando

Por exemplo, esse comando w gravará em outfile (faça uma cópia):

$ printf '%s\n' AA BB CC DD EE > infile
$ sed -n 'w outfile' infile
$ cat outfile
AA
BB
CC
DD
EE

A opção -n evita imprimir qualquer espaço padrão, mas o comando w irá write de cada padrão (linha) para o nome do arquivo no argumento após o comando w (que deve terminar o comando). / p>

Isso, em vez disso, irá escrever apenas uma linha (a linha que tem (pelo menos) um C ):

$ sed -n '/C/ w outfile' infile ;  cat outfile
CC

bandeira

O outro elemento w é o w para o comando s/// , que, embora signifique o mesmo write , só será executado se a substituição no comando s/// for executada:

$ sed -n 's/C/X/w outfile' infile; cat outfile
XC

Q1

But where do I put the w substitution flag if I'm using multiple commands and want the results wrote to a file?

Como um sinalizador de substituição está conectado a uma substituição (específica), onde deve ser usado depende de qual substituição precisa ser registrada:

$ sed -n -e 's/B/X/w outfile' -e 's/D/Y/' infile; cat outfile
XB

Observe que cada substituição deve estar em -e (ou linhas separadas) separadas, pois o nome do nome do arquivo de saída deve terminar com o comando (precisa de uma nova linha) ou pode ser escrito como:

$ sed -n -e 's/B/X/w outfile
> s/D/Y/' infile; cat outfile
XB

A outra substituição pode ser selecionada com:

$ sed -n -e 's/B/X/' -e 's/D/Y/w outfile' infile; cat outfile
YD

Ou ambos:

$ sed -n -e 's/B/X/w outfile' -e 's/D/Y/w outfile' infile; cat outfile
XB
YD

Ou use o comando w (não sinalizar) (e supondo que o GNU sed):

$ sed -n 's/B/X/;s/D/Y/;w outfile' infile; cat outfile
AA
XB
CC
YD
EE

Q2

I want to write the whole output to the file, a copy of the original with the changes made.

Um sinalizador substituição não pode gravar o arquivo inteiro , a menos que a substituição ocorra em todas as linhas. Você precisa usar o comando w (assumindo bash):

$ printf 'The quick brown fox jumps over the lazy dog%.0s\n' {1..14} >catAndDog.txt
$ sed -n '4 { s/fox/elephant/ ; s/dog/cat/ } ; w outfile' catAndDog.txt
$ cat outfile
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown elephant jumps over the lazy cat
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog

Entenda que um sinalizador w para cada substituição imprimirá uma linha para cada substituição, então isso acontecerá:

$ sed -n -e '4 { s/fox/elephant/w outfile' -e 's/dog/cat/w outfile' -e '}' catAndDog.txt
$ cat outfile
The quick brown elephant jumps over the lazy dog
The quick brown elephant jumps over the lazy cat
    
por 10.09.2018 / 09:43
2

Em resposta a:

I want to write the whole output to the file, a copy of the original with the changes made.

Você pode redirecionar para um arquivo como

sed '4{ s/fox/elephant/; s/dog/cat/}' infile > modified_file

Ou modifique no local com -i flag:

sed -i '4{ s/fox/elephant/; s/dog/cat/}' infile

... ou faça um backup do arquivo original e escreva as alterações com o mesmo nome de arquivo original.

sed -i.backup '4{ s/fox/elephant/; s/dog/cat/}' infile

Ou com o comando w :

sed '4{ s/fox/elephant/; s/dog/cat/ }; w modified_file' infile

Se você quiser apenas escrever as linhas que a substituição do comando s foi bem-sucedida (que não é o que você está pedindo atualmente), usando o w flag que você pode fazer:

sed '4{ s/fox/elephant/; s/dog/cat/w modified_file
}' infile
    
por 06.09.2018 / 21:01
2

But where do I put the w substitution flag if I'm using multiple commands and want the results wrote to a file?

O sinalizador w deve ser finalizado com uma nova linha ou deve ser o último item (incluindo o argumento) em um script sed. Se forem encontrados espaços em branco, comentários ou ponto e vírgula, eles serão incluídos no nome do arquivo.

Não confunda o sinalizador w associado à substituição de comando s ( s///w ) e o comando w . Eles são semelhantes, mas o sinalizador w é usado apenas se a substituição for executada. Observe que o comando w pode ser usado condicional ou incondicionalmente, dependendo do script sed (casos de uso).

Nota: a opção i ( --in-place ) não é especificada por POSIX.

Primeiro exemplo

prompt% sed -i.back -e "/$regex/w output" -e "/$regex/d" input

Segundo exemplo

prompt% sed -i.back "/$regex/ {
w output
d;}" input

Alguém pode encontrar um problema com seu caso (veja abaixo) porque várias substituições são realizadas na mesma linha de entrada.

prompt% sed -n '4 { 
s/fox/wolf/w output
s/dog/bear/w output
}' input

Existe apenas uma linha de entrada modificada, mas o arquivo de saída contém duas linhas.

The quick brown wolf jumps over the lazy dog
The quick brown wolf jumps over the lazy bear

Esse resultado não é conveniente porque é enganoso.

I want to write the whole output to the file, a copy of the original with the changes made.

Minha solução permite criar um backup do arquivo original ( input.back ), aplicar alterações no arquivo original ( input ) e gravar possíveis substituições em outro arquivo ( output ). Este algoritmo usa o comando w .

prompt% sed -i.back -nE '4!p       # print line except 4th
4!d                                # delete line except 4th
/fox|dog/!p                        # print line if no "fox" or no "dog"
/fox|dog/!d                        # don't delete line if "fox" or "dog"
s/fox/wolf/                        # substitution occurs if "fox"
s/dog/bear/                        # substitution occurs if "dog"
p                                  # if a substitution then print 4th line
w output' input                    # if a change then save 4th line in "output"

O comando /fox|dog/!d inicia imediatamente o próximo ciclo se fox ou dog não for encontrado (nenhum deles). Portanto, se uma palavra-chave não for encontrada, os seguintes comandos ( s/// , p , w ) não serão processados para a linha atual.

    
por 09.09.2018 / 22:43