Como concatenar várias linhas de saída para uma linha?

158

Se eu executar o comando cat file | grep pattern, recebo muitas linhas de saída. Como você concatena todas as linhas em uma linha, substituindo efetivamente cada uma "\n"por "\" "(finalize com "seguido por espaço)?

cat file | grep pattern | xargs sed s/\n/ /g não está funcionando para mim.

T. Webster
fonte
A propósito: (1) você precisa colocar seu sedscript entre aspas simples para que o Bash não mexa com ele (já que sed s/\n/ /gchama sedcom dois argumentos, a saber, s/n/e /g); (2) desde que você quer a saída de cat file | grep patternser a entrada para sed, e não os argumentos para sed, você precisa eliminar xargs; e (3) não há necessidade cataqui, pois greppode usar um nome de arquivo como seu segundo argumento. Então, você deveria ter tentado grep pattern file | sed 's/\n/ /g'. (Neste caso, não teria funcionado, por razões dadas no link acima, mas agora você sabe o futuro.) #
Ruakh
semelhante a " stackoverflow.com/questions/2764051/… "
Shervin Emami 28/04
Pergunta com 68 votos (140k visualizações) duplicada com postagem que possui apenas 1 voto (12k visualizações)? Isso não está certo.
Kenorb # 29/18

Respostas:

231

Use tr '\n' ' 'para converter todos os caracteres de nova linha em espaços:

$ grep pattern file | tr '\n' ' '

Nota: greplê arquivos, catconcatena arquivos. Não cat file | grep!

Editar:

trpode lidar apenas com traduções de caracteres únicos. Você pode usar awkpara alterar o separador de registros de saída como:

$ grep pattern file | awk '{print}' ORS='" '

Isso transformaria:

one
two 
three

para:

one" two" three" 
Chris Seymour
fonte
3
Você termina com um espaço indesejado no final com essa abordagem.
sorin 21/03
1
Você precisa adicionar echo ""no final para adicionar nova linha antes do texto do prompt.
Nexayq 09/09/16
1
Isso funciona muito bem, no entanto, não quero que o separador apareça na última entrada. Por exemplo, por exemplo, "ele aparece como one" two" three", no entanto, eu gostaria que ele aparecesse one" two" three. Observe que os três últimos não têm parênteses. Alguma ideia?
oink
2
@ link você pode canalizar os resultados sed '$s/..$//'para excluir os 2 últimos caracteres da última linha.
Chris Seymour
3
Se você deseja substituir as novas linhas por nada, é necessário usar a --deleteopção, pois o padrão espera dois argumentos. por exemplo tr --delete '\n'.
Elias Lynn
69

A saída da tubulação xargsconcatenará cada linha de saída em uma única linha com espaços:

grep pattern file | xargs

Ou qualquer comando, por exemplo. ls | xargs. O limite padrão de xargssaída é ~ 4096 caracteres, mas pode ser aumentado com, por exemplo. xargs -s 8192.

bluebadge
fonte
| tr '\n' ' 'não estava funcionando para mim quando chamado através da php execfunção. Estava ignorando tr, e apenas dando a última partida do grep. | xargstrabalhou.
Adarsha
3
Essa solução também tem a vantagem de "consumir" espaços da entrada. +1
Rene
55

No bash echosem aspas, remova retornos de carro, tabulações e vários espaços

echo $(cat file)
user1699917
fonte
8
Resposta severamente subestimada aqui, isso é realmente simples e funciona como um encanto, com uma nova linha à direita também.
Dangercrow
Isto é especialmente puro, se você usarIFS="$(printf '\n\t')"
aggsol
5
Ou apenas echo $(<file)... usar eco não é apenas mais puro do que usar tr '\n' ' ', mas também melhor (pense nos \r\nfinais das linhas). @aggsol você pode apenas dizerIFS=$'\n\t'
Normadize
Que tal sem espaço?
DimiDak 28/11/19
22

Pode ser o que você quer

cat file | grep pattern | paste -sd' '

Quanto à sua edição, não tenho certeza do que isso significa, talvez isso?

cat file | grep pattern | paste -sd'~' | sed -e 's/~/" "/g'

(isso pressupõe que ~não ocorra em file)

ver
fonte
2
@Stephan não havia necessidade de assumir que cat filerealmente será cat, ou mesmo um arquivo. (Eu só deixou essa parte inalteradas como era irrelevante para a questão)
sehe
5

Este é um exemplo que produz saída separada por vírgulas. Você pode substituir a vírgula por qualquer separador necessário.

cat <<EOD | xargs | sed 's/ /,/g'
> 1
> 2
> 3
> 4
> 5
> EOD

produz:

1,2,3,4,5
Richard Gomes
fonte
3

Aqui está o método usando o exeditor (parte do Vim ):

  • J oin todas as linhas e p rint para a saída padrão:

    $ ex +%j +%p -scq! file
  • Em todas as linhas no local (no arquivo):

    $ ex +%j -scwq file

    Nota: Isso concatenará todas as linhas dentro do próprio arquivo!

kenorb
fonte
2

As maneiras mais rápidas e fáceis de solucionar esse problema:

Quando queremos substituir o novo caractere de linha \n pelo espaço :

xargs < file

xargspossui limites próprios no número de caracteres por linha e no número de todos os caracteres combinados, mas podemos aumentá-los. Detalhes podem ser encontrados executando este comando: xargs --show-limitse, claro, no manual:man xargs

Quando queremos substituir um caractere por outro, exatamente um caractere :

tr '\n' ' ' < file

Quando queremos substituir um caractere por muitos caracteres :

tr '\n' '~' < file | sed s/~/many_characters/g

Primeiro, substituímos os caracteres de nova linha \npor til ~(ou escolhemos outro caractere exclusivo que não está presente no texto) e, em seguida, substituímos os caracteres de til por outros caracteres ( many_characters) e fazemos isso para cada til (sinalizador g).

simhumileco
fonte
0

Provavelmente, a melhor maneira de fazer isso é usar a ferramenta 'awk', que gerará saída em uma linha

$ awk ' /pattern/ {print}' ORS=' ' /path/to/file

Ele mesclará todas as linhas em uma com delimitador de espaço

Vladimir Yahello
fonte
Você não precisa, {print}pois é a ação padrão do awk.
stark
0

Aqui está outro método simples usando awk:

# cat > file.txt
a
b
c

# cat file.txt | awk '{ printf("%s ", $0) }'
a b c

Além disso, se o seu arquivo tiver colunas, isso oferece uma maneira fácil de concatenar apenas determinadas colunas:

# cat > cols.txt
a b c
d e f

# cat cols.txt | awk '{ printf("%s ", $2) }'
b e
ascendentes
fonte
-1

No red hat linux, eu apenas uso echo:

eco $ (cat / some / file / name)

Isso me fornece todos os registros de um arquivo em apenas uma linha.

user13498546
fonte
2
Isso já foi respondido em 2015. Você está apenas duplicando esta resposta . Leia as respostas antes de postar as suas, especialmente quando a pergunta tiver 7 anos e já houver 8 respostas.
Mickael B.