No Bash, como adiciono uma string após cada linha em um arquivo?

112

Como adiciono uma string após cada linha em um arquivo usando o bash? Isso pode ser feito usando o comando sed, se sim, como?

Jason Volkoz
fonte

Respostas:

188

Se você sedpermitir a edição no local por meio do -iparâmetro:

sed -e 's/$/string after each line/' -i filename

Caso contrário, você deve fazer um arquivo temporário:

typeset TMP_FILE=$( mktemp )

touch "${TMP_FILE}"
cp -p filename "${TMP_FILE}"
sed -e 's/$/string after each line/' "${TMP_FILE}" > filename
Tom DeGisi
fonte
Por que você faz toucho arquivo temporário? E eu tornaria o sedcomando condicional ao sucesso do cpou o original poderia ser perdido.
Pausado até novo aviso.
Toquei no arquivo para reservar rapidamente o nome temporário. Isso pode não ser necessário. Acho que você está certo sobre tornar o comando sed condicional ao sucesso do cp. Por que não editar o código para fazer essa correção. Eu não vou me importar nem um pouco! Atenciosamente, Tom
Tom DeGisi
Que tal adicionar uma string antes de uma linha?
Oxwivi
10
@Oxwivi: sed -e 's/^/string after each line/' -i filename $ significa fim de linha. ^ significa início da linha.
Tom DeGisi
Se eu estou canalizando para o sed, sed 's/^/string after each line/'faz o que eu esperava (adiciona cada linha), mas sed 's/^/string after each line/'não (substitui toda a linha pela minha string anexada). O que da? Alguma ideia @TomDeGisi?
philadams
17

Eu prefiro usar awk. Se houver apenas uma coluna, use $0, do contrário, substitua-a pela última coluna.

Mão única,

awk '{print $0, "string to append after each line"}' file > new_file

ou isto,

awk '$0=$0"string to append after each line"' file > new_file
Optimus Prime
fonte
1
Além disso, para acrescentar números de linha (como foi no meu caso), pode-se usar a NRvariável:awk '{print $0, NR}'
andrybak
2
@optimus Tentei seu método, mas conseguindo um espaço extra entre eles, alguma ideia de como removê-los?
Adil Saju
@AdilSaju sed 's/ //g'isso funcionou para minhas necessidades, mas irá remover espaço em todas as linhas, essa é a opção gpara e em todos os lugares em uma linha.
Eklavyaa
@AdilSaju adicione detalhes. Melhor fazer uma nova pergunta.
Optimus Prime
@AdilSaju awk Remover , gosto {print $0"string to append after each line"}.
Culip
8

Se você tiver, o utilitário lam (laminado) pode fazer isso, por exemplo:

$ lam filename -s "string after each line"
martin clayton
fonte
4
  1. Casca POSIX pura e sponge:

    suffix=foobar
    while read l ; do printf '%s\n' "$l" "${suffix}" ; done < file | 
    sponge file
    
  2. xargse printf:

    suffix=foobar
    xargs -L 1 printf "%s${suffix}\n" < file | sponge file
    
  3. Usando join:

    suffix=foobar
    join file file -e "${suffix}" -o 1.1,2.99999 | sponge file
    
  4. Ferramentas Shell usando paste, yes, head e wc:

    suffix=foobar
    paste file <(yes "${suffix}" | head -$(wc -l < file) ) | sponge file
    

    Observe que pasteinsere um caractere Tab antes $suffix.

Claro que spongepode ser substituído por um arquivo temporário, depois mvsobre o nome do arquivo original, como acontece com algumas outras respostas ...

agc
fonte
1
Nenhum desses é preferível sed, a menos que os recursos sejam muito limitados.
agc
Eu gosto da solução não sed. sednão é necessário para um trabalho tão simples.
Bruce
1

Eu prefiro echo. usando bash puro:

cat file | while read line; do echo ${line}$string; done
欢乐 的 Xiaox
fonte
-9

Sed é um pouco feio, você poderia fazer isso elegantemente assim:

hendry@i7 tmp$ cat foo 
bar
candy
car
hendry@i7 tmp$ for i in `cat foo`; do echo ${i}bar; done
barbar
candybar
carbar
Hendry
fonte
2
Falha para arquivos com mais linhas do que o limite máximo de argumentos do shell. Experimente: cat foo | enquanto lê um; faça echo $ {a} bar; feito ou algo parecido; é um substituto adequado para na maioria dos casos.
alex
1
Também falha para linhas com espaços nelas.
Pausado até novo aviso.
1
Er, não, não falha Dennis. limite máximo de argumentos do shell? Caramba, você está sendo pendente.
hendry de
Sim, é verdade: $ cat foo foo bar baz alex @ armitage: ~ $ for i in cat foo; faça echo $ {i} bar; feito foobar barbar bazbar, mas depois de alguns testes, posso estar errado sobre meu raciocínio, mas Dennis está certo
alex de
3
@hendry Sim, isso falha para linhas com espaços, como o echo "foo bar" | (for i in `cat`; do echo ${i}bar; done)que imprime 2 linhas mesmo que a entrada seja 1 linha foo bar(e catler de stdin ao invés de um arquivo não faz diferença para isso).
hyde