Qual é a maneira mais fácil de adicionar uma string no início de cada linha do arquivo na linha de comando?


8

Eu estou procurando uma maneira de adicionar uma seqüência de caracteres para o início de cada linha (mesma seqüência de caracteres para cada linha). Não é algo personalizável, mas algo fácil de lembrar e disponível em todas as plataformas compatíveis com POSIX (e também em todos os shell).

Respostas:


8

Você pode usar sed:

sed -i 's/^/your_string /' your_file

Graças aos comentários de Stephane e Marco, observe que a -iopção não é POSIX. Uma maneira POSIX de fazer o acima seria

sed 's/^/your_string /' your_file > tmp_copy && mv tmp_copy your_file

ou perl:

perl -pi -e 's/^/your_string /' your_file

Explicação

Ambos os comandos executam uma substituição de regex, substituindo o início de uma linha ( ^) pela string desejada. A -iopção nos dois comandos garante que o arquivo seja editado no local (ou seja, as alterações são refletidas no arquivo em vez de impressas no stdout).

seddeve estar disponível em qualquer sistema operacional compatível com POSIX e perlestar disponível na maioria dos Unices modernos, exceto talvez nos que passaram pelo esforço de removê-lo.


1
Correção pequena: a -iopção não edita o arquivo no local. Ele cria um novo arquivo e sobrescreve o original após a conclusão (prova: o inode é alterado). Não existem muitas ferramentas que efetuem a edição no local, o que é uma operação perigosa. Além disso, como você menciona o POSIX, o -iswitch não é obrigatório para um compatível com POSIX sed, é um recurso de algumas implementações específicas.
Marco

2
sed -inão é POSIX. É o GNU. O FreeBSD sedtem uma opção semelhante, mas você precisa de sed -i ''lá.
Stéphane Chazelas

@Marco Estou ciente de que -icria uma cópia temporária (é por isso que eu disse que as alterações são refletidas no arquivo original); Eu quis dizer que você obtém a mesma semântica que a substituição no local. Verifique se a resposta atualizada é compatível com POSIX.
Joseph R.

A rigor, as alterações são refletidas em um novo arquivo com o mesmo nome que o original.
Keith Thompson

1
Costumo usar $$(o ID do processo do shell atual) como parte de um nome de arquivo temporário; evita o esforço de pensar em um nome único garantido sempre:command filename > filename.$$ && mv filename.$$ filename
Keith Thompson

14
:|paste -d'foo ' - - - - input > output

(Brincadeirinha, embora você provavelmente descubra que é a mais rápida de todas as soluções postadas aqui: -b).

O caminho canônico é:

sed 's/^/foo /' < input > output

No entanto, não é facilmente adaptável a seqüências arbitrárias. Por exemplo,

sed "s/^/$var /"

Só funciona se $varnão contém, &, \, /nem caracteres de nova linha.

Nesse sentido,

export var
awk '{print ENVIRON["var"], $0}'

ou

perl -pe '$_="$ENV{var} $_"'

funcionaria melhor.


isso é algo interessante ...: P
Rahul Patil

4

Apresento uma solução usando o awkprefixo "foo".

awk '{ print "foo", $0; }' input > output

awké multiplataforma e está disponível em qualquer sistema POSIX. Não realiza edição no local. Se você deseja editar um arquivo sem criar um segundo, precisará usar um arquivo temporário. Veja a sedresposta de Joseph , mostra a sintaxe. Outro truque é usar a seguinte sintaxe, que basicamente cria um arquivo temporário com o mesmo nome que o arquivo original.

{ rm file; awk '{ print "foo", $0 }' > file; } < file

reducto# wc -l foo914 foo` reducto# { rm foo ; awk '{ print "prepend" , $0 }' > foo } < foo >Isso parece não funcionar. Eu estava tentando, porque o redirecionamento para o original me deixou nervoso, mas nem sequer começou.
Kurtm

1
Este exemplo funcionará se ele usar parênteses para o exterior, em vez de chaves.
Kurtm # 8/13

4

Você pode evitar os problemas de edição no local com as ferramentas de fluxo usando uma ferramenta que normalmente faz a edição no local - um editor!

ex sample.txt -c "%s/^/foo /" -c wq

Há uma vantagem adicional de que os comandos são fáceis e óbvios para quem é versado no único editor verdadeiro.


2

Você pode usar perlpara fazer isso:

$ perl -pi -e 's/^/mystring /' afile.txt

Exemplo

Crie um arquivo de amostra.

$ seq 5 > afile.txt

$ cat afile.txt
1
2
3
4
5

Execute o comando acima:

$ perl -pi -e 's/^/mystring /' afile.txt

$ cat afile.txt
mystring 1
mystring 2
mystring 3
mystring 4
mystring 5

Perl parece ser universal hoje em dia, mas por um longo tempo não foi. E aposto que existem algumas variantes raras do UNIX por aí que se recusam firmemente a ter o perl como parte da base. Algo para estar ciente.
Kurtm

@kurtm veja a discussão aqui . Aparentemente, o AIX não possui Perl por padrão e nem sistemas incorporados.
terdon

2
@ DavidSainty - é universal o suficiente. O Q foi marcado com o Bash, então acho extremamente difícil imaginar um sistema que tenha o Bash, mas não o Perl. De qualquer forma, aqui está uma das 5 respostas, várias das outras mostram como usar sed, eu mostrei como usar Perl .... não procurando uma guerra santa sobre o assunto.
slm

1
@DavidSainty Aparentemente apenas o OpenBSD. Acho que assumi que o pessoal do Open tende a ser conservador quanto ao que eles permitem na base. O OpenBSD definitivamente o possui na base.
kurtm

1
@slm: " Acho extremamente difícil imaginar um sistema que tenha o Bash, mas não o Perl ". Eu tenho vários desses sistemas em minha mesa. (Eles são sistemas embarcados.)
Keith Thompson

1

Simplesmente usando o Bash

 while IFS= read -r line; do echo "foo" "${line}" ; done  < input > Output

Usando Python

python -c "import sys; print 'foo '.join([ l for l in sys.stdin.readlines() ])" < input > Output

Se você deseja editar no local

import fileinput
import sys

for line in fileinput.input(['inputfile'], inplace=True):
    sys.stdout.write('foo {l}'.format(l=line))

Link de referência


Por que está funcionando mais rápido que o awk?
Rahul Patil

1
Só vai funcionar mais rápido do que awkem arquivos muito pequenos. O comportamento varia nas implementações de eco e elimina os espaços em branco iniciais e finais e processa as barras invertidas especialmente.
Stéphane Chazelas

@StephaneChazelas Yes. você está 100% correto apenas testado ... paste.ubuntu.com/6210934
Rahul Patil

prefix () { while IFS= read -r REPLY; do printf "%s%s\n" "$1" "$REPLY"; done; }deveria ser mais correto.
Matt

1
Por que o {}? Eu acho que o @Matt estava sugerindo que você transformasse em uma função nomeada, qual é o sentido de {}sem um nome de função?
terdon

-1

Ou você pode fazer o seguinte:

vi filename.txt

Esc(para garantir que você esteja no NORMALmodo) e digite o seguinte comando:

:1,$ s/^/mystring

Observe que, como o usuário está perguntando sobre todas as linhas do arquivo, você pode substituir 1,$ por simplesmente %. Isso faz o comando :%s/^/string/.
precisa saber é o seguinte
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.