Formatta l'output di xargs


10

Vorrei cambiare il formato dei display di output xargs

cat k.txt 
1 
2 
3 

E

cat k.txt | xargs 
1 2 3

Tuttavia vorrei 1, 2, 3o 1|2|3. Eventuali suggerimenti?


Questo potrebbe essere raggiunto con qualcosa (non esattamente questo) come xargs cat -n, ma è più facile se si tagliare i caratteri di nuova riga, questo può essere realizzato con echo $(cat), grepo awk(strisciare il modo per farlo). xargsnon andare bene per il tuo scopo attuale.
41754,

Risposte:


18

Di seguito sono riportati una dozzina di esempi di come è possibile prendere un file come questo:

$ cat k.txt
1
2
3

e convertilo in questo formato:

1,2,3

Puoi usare questo comando per creare il file sopra se vuoi giocare insieme:

$ cat <<EOF > k.txt
1
2
3
EOF

Gli esempi seguenti sono divisi in 2 gruppi. Quelli che "funzionano" e quelli che "quasi" funzionano. Lascio questi perché spesso volte è altrettanto prezioso vedere perché qualcosa non funziona, come è vedere perché qualcosa funziona.

Sono rappresentati la maggior parte dei linguaggi di scripting con cui ho familiarità. Alcuni sono rappresentati più volte, poiché come nel famoso acronimo a cui si fa riferimento in Perl, TIMTOWTDI .

NOTA: è possibile sostituire la virgola ( ,) negli esempi seguenti e sostituirla con qualsiasi carattere desiderato, ad es |.

Esempi che "funzionano"

Questi frammenti di codice produrranno l'output desiderato.

Il pastecomando:

$ paste -s -d ',' k.txt 
1,2,3

Il sedcomando:

$ sed ':a;N;$!ba;s/\n/,/g' k.txt
1,2,3

$ sed ':a;{N;s/\n/,/};ba' k.txt 
1,2,3

Il perlcomando:

$ perl -00 -p -e 's/\n(?!$)/,/g' k.txt
1,2,3

$ perl -00 -p -e 'chomp;tr/\n/,/' k.txt
1,2,3

Il awkcomando:

$ awk '{printf"%s%s",c,$0;c=","}' k.txt
1,2,3

$ awk '{printf "%s,",$0}' k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

$ awk -vORS=, 1 k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

$ awk 'BEGIN {RS="dn"}{gsub("\n",",");print $0}' k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

Il pythoncomando:

$ python -c "import sys; print sys.stdin.read().replace('\n', ',')[0:-1]" <k.txt
1,2,3

$ python -c "import sys; print sys.stdin.read().replace('\n', ',').rstrip(',')" <k.txt
1,2,3

Bash mapfileintegrato:

$ mapfile -t a < k.txt; (IFS=','; echo "${a[*]}")
1,2,3

Il rubycomando:

$ ruby -00 -pe 'gsub /\n/,",";chop' < k.txt
1,2,3

$ ruby -00 -pe '$_.chomp!"\n";$_.tr!"\n",","' k.txt
1,2,3

Il phpcomando:

$ php -r 'echo strtr(chop(file_get_contents($argv[1])),"\n",",");' k.txt
1,2,3

Avvertenze

La maggior parte degli esempi sopra funzionerà perfettamente. Alcuni hanno problemi nascosti, come l'esempio di PHP sopra. La funzione chop()è in realtà un alias rtrim(), quindi verranno rimossi anche gli spazi finali dell'ultima riga.

Lo stesso vale per il primo esempio di Ruby e il primo esempio di Python. Il problema è come stanno tutti usando un tipo di operazione che essenzialmente "taglia", alla cieca, un personaggio finale. Questo va bene nell'esempio fornito dall'OP, ma occorre fare attenzione quando si usano questi tipi di rivestimenti per assicurarsi che siano conformi ai dati che stanno elaborando.

Esempio

Pronuncia il nostro file di esempio, k.txtassomiglia invece a questo:

$ echo -en "1\n2\n3" > k.txt

Sembra simile ma ha una leggera differenza. Non ha una nuova riga finale ( \n) come il file originale. Ora quando eseguiamo il primo esempio di Python otteniamo questo:

$ python -c "import sys; print sys.stdin.read().replace('\n', ',')[0:-1]" <k.txt
1,2,

Esempi che "quasi" funzionano

Questi sono gli esempi "sempre una damigella d'onore, mai una sposa" . Molti di essi potrebbero probabilmente essere adattati, ma quando si lavora su una potenziale soluzione a un problema, quando sembra "forzato", è probabilmente lo strumento sbagliato per il lavoro!

Il perlcomando:

$ perl -p -e 's/\n/,/' k.txt
1,2,3,

Il trcomando:

$ tr '\n' ','  < k.txt 
1,2,3,

I comandi cat+ echo:

$ echo $(cat k.txt)
1 2 3

Il rubycomando:

$ ruby -pe '$_["\n"]=","' k.txt
1,2,3,

Bash's while+ readbuilt-in:

$ while read line; do echo -n "$line,"; done < k.txt
1,2,3,

1
Per quanto riguarda awkpreferisco un'alternativa più breve:awk -vORS=, 1 k.txt
manatwork

Non sono sicuro che CentOS abbia bash:mapfile -t a < k.txt; (IFS=','; echo "${a[*]}")
manatwork

non sono sicuro della nuova riga finale. Secondo il mio test, anche tu perle prima awkli hai .
arte

Vorrei mettere pastequello in alto. Questo è esattamente ciò che paste -sè qui. È un comando standard e sarebbe il più efficiente. Tutti gli altri sono eccessivi e / o non portatili o con limitazioni.
Stéphane Chazelas,

mapfileè relativamente nuovo, aggiunto in bash4.0.
Manatwork

4

@slm ha già dato una bella risposta, ma come domanda "formatta l'output di xargs"

xargs -I{} echo -n "{}|" < test.txt
  • -I è l'opzione "sostituisci stringhe".
  • {} è un segnaposto per il testo di output.
  • Questo è simile all'uso di una coppia di parentesi graffe in "trova".

Se vuoi sbarazzarti del trailing |puoi usare sedper fare un po 'di pulizia:

$ xargs -I{} echo -n "{}|" < k.txt  | sed -e 's/|$//'
1|2|3

Questo aggiunge un tubo in più dopo il 3. "1 | 2 | 3 |". Ho avuto lo stesso problema con un ciclo while e una soluzione awk.
slm

sì, se c'è una nuova linea .. tr, sede anche altre ..
Rahul Patil,

2

Questo è un vecchio thread, lo so. L'OP ha chiesto con un semplice codice come questo. Per tenerlo vicino all'originale, ho una soluzione semplice.

cat k.txt | xargs
1 2 3

usa sed

cat k.txt | xargs | sed 's/ /,/g'
1,2,3

o

cat k.txt | xargs | sed 's/ /|/g'
1|2|3

sed può sembrare un po 'strano ma scomposto, ha molto senso.

è per il sostituto. g 'è per globale: senza questo, farà solo la prima sostituzione su ogni nuova linea. Dato che usi 'xargs', li visualizza come una riga. Quindi otterrai "1,2 3".

Il delimitatore viene utilizzato per la separazione. Ho usato il carattere /. Un trucco interessante: puoi sostituire il delimitatore con quasi tutti gli altri personaggi, purché lo manteniamo nello stesso formato tra le virgolette. Quindi funzionerebbe anche ...

cat k.txt | xargs | sed 's# #,#g'

o

cat k.txt | xargs | sed 'sT T,Tg'

Ovviamente, l'utilizzo di determinati caratteri come delimitatore può creare confusione, quindi sii intelligente.


0
xargs <k.txt | tr \  \|

Non è necessario cat- basta inserire l'input del file e - se non viene dato nessun altro comando - xargsverrà trasmesso il suo formato predefinito - che è di un tipo con /bin/echo's (senza interpretazioni di c-escape con barra rovesciata) .

xargseliminerà gli spazi bianchi testa / coda dal file di input e comprimerà altre sequenze di spazi bianchi in un singolo spazio. Ciò significa che mentre si passa il file tra xargscome:

tr \\n \| <k.txt | xargs

... stampe ...

1|2|3|

... andando dall'altra parte e operando solo sulle argomentazioni che xargsi delimiti spaziali fanno ...

1|2|3\n

... perché xargsstampa la riga finale finale (come richiesto per un file di testo) , ma non viene trrisposto in questo modo.

Si noti, tuttavia, che questa (o qualsiasi altra soluzione offerta qui) non tiene conto della xargsquotazione in input. xargsdistribuirà letteralmente caratteri non-newline tra virgolette singole / doppie / con barra rovesciata in input, che possono esse stesse essere quotate come:

xargs <<\IN
1    2'      3'\'      \'4
IN

1 2      3' '4
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.