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?

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

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

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"

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 ...


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

-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

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
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.