Come concatenare più righe di output su una riga?


157

Se eseguo il comando cat file | grep pattern, ottengo molte righe di output. Come concatenate tutte le linee in una riga, sostituendole efficacemente "\n"con "\" "(end with "seguita da spazio)?

cat file | grep pattern | xargs sed s/\n/ /g non funziona per me.


A proposito: (1) devi mettere il tuo sedscript tra virgolette singole in modo che Bash non si scherzi (dal momento che sed s/\n/ /gchiama sedcon due argomenti, vale a dire s/n/e /g); (2) da quando si desidera che l'uscita di cat file | grep patternessere l' ingresso a sed, non gli argomenti a sed, è necessario eliminare xargs; e (3) non è necessario catqui, poiché greppuò prendere un nome file come secondo argomento. Quindi avresti dovuto provare grep pattern file | sed 's/\n/ /g'. (In questo caso non avrebbe funzionato, per motivi indicati nel link sopra, ma ora lo sai per il futuro.)
ruakh


Domanda con 68 voti (140k visualizzazioni) duplicata con un post che ha solo 1 voto (12k visualizzazioni)? Questo non è giusto
Kenorb,

Risposte:


230

Utilizzare tr '\n' ' 'per tradurre tutti i caratteri di nuova riga in spazi:

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

Nota: greplegge i file, catconcatena i file. Non farlo cat file | grep!

Modificare:

trpuò gestire solo traduzioni di singoli caratteri. È possibile utilizzare awkper modificare il separatore del record di output come:

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

Ciò trasformerebbe:

one
two 
three

per:

one" two" three" 

3
Con questo approccio finisci con uno spazio indesiderato alla fine.
sorin,

1
È necessario aggiungere echo ""alla fine per aggiungere una nuova riga prima del testo del prompt.
Nexayq,

1
Funziona bene, tuttavia non voglio che il separatore venga visualizzato nell'ultima voce. Esempio, per il tuo ", si presenta come one" two" three", tuttavia vorrei che si presentasse come one" two" three. Nota che gli ultimi tre non hanno una parentesi. Qualche idea?
Oink

2
@oink potresti reindirizzare i risultati sed '$s/..$//'per eliminare gli ultimi 2 caratteri sull'ultima riga.
Chris Seymour,

3
Se si desidera sostituire le nuove righe con nulla, è necessario utilizzare l' --deleteopzione poiché l'impostazione predefinita prevede due argomenti. es tr --delete '\n'.
Elijah Lynn il

69

Il piping dell'output a xargsconcatenerà ogni riga di output su una singola riga con spazi:

grep pattern file | xargs

O qualsiasi comando, ad es. ls | xargs. Il limite predefinito di xargsoutput è ~ 4096 caratteri, ma può essere aumentato con es. xargs -s 8192.


| tr '\n' ' 'non funzionava per me quando chiamato tramite la php execfunzione. Stava ignorando tr e stava dando l'ultima partita da grep. | xargslavorato.
Adarsha,

3
Questa soluzione ha anche il vantaggio di "mangiare" spazi dall'input. +1
Rene,

55

In bash echosenza virgolette rimuovere i ritorni a capo, le schede e gli spazi multipli

echo $(cat file)

8
Risposta severamente sottovalutata qui, è davvero semplice e funziona come un incantesimo, con anche una nuova riga finale.
Dangercrow

Questo è particolarmente pulito se lo usiIFS="$(printf '\n\t')"
aggsol il

5
O semplicemente echo $(<file)... usare l'eco non è solo più pulito dell'uso tr '\n' ' ', ma anche migliore (pensa alle \r\nterminazioni di linea). @aggsol puoi solo direIFS=$'\n\t'
Normadize

Che ne dici di senza spazio?
DimiDak,

22

Questo potrebbe essere quello che vuoi

cat file | grep pattern | paste -sd' '

Quanto alla tua modifica, non sono sicuro di cosa significhi, forse questo?

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

(questo presuppone che ~non si verifichi in file)


2
@Stephan non è stato necessario supporre che cat filesarà effettivamente cat, o anche un file. (Ho lasciato quella parte invariata perché irrilevante per la domanda)
vedi il

5

Questo è un esempio che produce output separato da virgole. Puoi sostituire la virgola con qualunque separatore ti serva.

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

produce:

1,2,3,4,5

3

Ecco il metodo usando l' exeditor (parte di Vim ):

  • J oin tutte le linee e p tampa sullo standard output:

    $ ex +%j +%p -scq! file
  • J oin tutte le linee in-place (nel file):

    $ ex +%j -scwq file

    Nota: questo concatenerà tutte le righe all'interno del file stesso!


2

I modi più semplici e veloci che conosco per risolvere questo problema:

Quando vogliamo sostituire il nuovo carattere di linea \n con lo spazio :

xargs < file

xargsha i propri limiti sul numero di caratteri per riga e sul numero di tutti i caratteri combinati, ma possiamo aumentarli. I dettagli possono essere trovati eseguendo questo comando: xargs --show-limitse ovviamente nel manuale:man xargs

Quando vogliamo sostituire un personaggio con un altro esattamente un personaggio :

tr '\n' ' ' < file

Quando vogliamo sostituire un carattere con molti caratteri :

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

Innanzitutto, sostituiamo i caratteri di nuova riga \nper le tilde ~(o scegliamo un altro carattere unico non presente nel testo), quindi sostituiamo i caratteri di tilde con qualsiasi altro carattere ( many_characters) e lo facciamo per ogni tilde (bandiera g).


0

Probabilmente il modo migliore per farlo è usare lo strumento 'awk' che genererà output in una riga

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

Unirà tutte le linee in una con delimitatore di spazio


Non è necessario {print}poiché è l'azione predefinita di awk.
rigido

0

Ecco un altro metodo semplice che utilizza awk:

# cat > file.txt
a
b
c

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

Inoltre, se il tuo file ha colonne, questo offre un modo semplice per concatenare solo determinate colonne:

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

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

-1

Su Red Hat Linux uso solo echo:

echo $ (cat / some / file / name)

Questo mi dà tutti i record di un file su una sola riga.


2
Questa è già stata una risposta nel 2015. Stai solo duplicando questa risposta . Leggi le risposte prima di pubblicare le tue, specialmente quando la domanda ha 7 anni e ci sono già 8 risposte.
Mickael B.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.