Memformat output xargs

10

Saya ingin mengubah format tampilan xargs keluaran

cat k.txt 
1 
2 
3 

Dan

cat k.txt | xargs 
1 2 3

Namun saya ingin memiliki 1, 2, 3atau 1|2|3. Ada saran?

Avinash
sumber
Itu bisa dicapai dengan sesuatu (tidak persis seperti ini) seperti xargs cat -n, tetapi lebih mudah jika Anda hanya memotong karakter baris baru, ini dapat dicapai dengan echo $(cat), grepatau awk(merangkak cara melakukannya). xargstidak cocok untuk tujuan Anda saat ini.
41754

Jawaban:

18

Di bawah ini ada sekitar selusin contoh cara Anda dapat mengambil file seperti ini:

$ cat k.txt
1
2
3

dan konversikan ke format ini:

1,2,3

Anda dapat menggunakan perintah ini untuk membuat file di atas jika Anda ingin bermain bersama:

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

Contoh di bawah ini dibagi menjadi 2 kelompok. Yang "bekerja" dan yang "hampir" bekerja. Saya meninggalkan ini karena sering kali itu sama berharganya dengan melihat mengapa sesuatu tidak bekerja, seperti melihat mengapa sesuatu bekerja.

Sebagian besar bahasa scripting yang saya kenal diwakili. Beberapa diwakili beberapa kali, karena seperti akronim terkenal yang biasanya dirujuk dalam Perl, TIMTOWTDI .

CATATAN: Anda dapat menukar koma ( ,) dalam contoh di bawah ini dan menggantinya dengan karakter apa pun yang Anda inginkan, yaitu |.

Contoh yang "berfungsi"

Cuplikan kode ini akan menghasilkan output yang diinginkan.

The pasteperintah:

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

The sedperintah:

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

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

The perlperintah:

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

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

The awkperintah:

$ 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

The pythonperintah:

$ 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 bawaan mapfile:

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

The rubyperintah:

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

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

The phpperintah:

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

Peringatan

Sebagian besar contoh di atas akan berfungsi dengan baik. Beberapa memiliki masalah tersembunyi, seperti contoh PHP di atas. Fungsi chop()ini sebenarnya adalah alias untuk rtrim(), jadi spasi trailing baris terakhir juga akan dihapus.

Demikian juga contoh Ruby pertama, dan contoh Python pertama. Masalahnya adalah bagaimana mereka semua menggunakan jenis operasi yang pada dasarnya "memotong", secara membabi buta, karakter yang tertinggal. Ini bagus untuk contoh yang diberikan OP, tetapi harus berhati-hati ketika menggunakan jenis satu liner ini untuk memastikan bahwa mereka sesuai dengan data yang mereka proses.

Contoh

Katakan file sampel kami, yang k.txtterlihat seperti ini:

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

Itu terlihat mirip tetapi memiliki satu sedikit perbedaan. Itu tidak memiliki trailing newline ( \n) seperti file asli. Sekarang ketika kita menjalankan contoh Python pertama kita mendapatkan ini:

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

Contoh yang "hampir" berfungsi

Ini adalah contoh "selalu pengiring pengantin, tidak pernah pengantin" . Sebagian besar dari mereka mungkin bisa diadaptasi, tetapi ketika bekerja solusi potensial untuk masalah, ketika rasanya "dipaksakan", itu mungkin alat yang salah untuk pekerjaan itu!

The perlperintah:

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

The trperintah:

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

The cat+ echoperintah:

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

The rubyperintah:

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

Bash's while+ readbawaan:

$ while read line; do echo -n "$line,"; done < k.txt
1,2,3,
slm
sumber
1
Mengenai awksaya lebih suka alternatif yang lebih pendek:awk -vORS=, 1 k.txt
manatwork
Tidak yakin apakah CentOS memiliki bash:mapfile -t a < k.txt; (IFS=','; echo "${a[*]}")
manatwork
tidak yakin tentang baris baru yang tertinggal. Menurut tes saya, Anda perldan pertama awkmemilikinya juga.
manatwork
Saya akan menempatkan yang pastedi atas. Itulah tepatnya paste -suntuk di sini. Ini adalah perintah standar dan akan menjadi yang paling efisien. Semua yang lain adalah berlebihan dan / atau tidak portabel atau memiliki keterbatasan.
Stéphane Chazelas
mapfilerelatif baru, ditambahkan pada bash4.0.
manatwork
4

@slm sudah memberikan jawaban yang bagus, tetapi sebagai pertanyaan Anda "format output of xargs"

xargs -I{} echo -n "{}|" < test.txt
  • -I adalah opsi "ganti string".
  • {} adalah pengganti untuk teks keluaran.
  • Ini mirip dengan penggunaan pasangan kurung-kurung di "find."

Jika Anda ingin menghilangkan trailing, |Anda dapat menggunakannya seduntuk melakukan pembersihan:

$ xargs -I{} echo -n "{}|" < k.txt  | sed -e 's/|$//'
1|2|3
Rahul Patil
sumber
Itu paku payung pipa tambahan setelah 3. "1 | 2 | 3 |". Saya mengalami masalah yang sama dengan solusi while dan loop.
slm
ya, jika ada baris baru .. tr, seddan lainnya juga ..
Rahul Patil
2

Ini adalah utas lama, saya tahu. OP bertanya dengan kode sederhana seperti ini. Untuk tetap dekat dengan aslinya, saya punya solusi sederhana.

cat k.txt | xargs
1 2 3

gunakan sed

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

atau

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

sed bisa terlihat sedikit aneh tapi rusak, itu masuk akal.

Ini untuk pengganti. g 'adalah untuk global: tanpa ini, ia hanya akan melakukan penggantian pertama pada setiap baris baru. Karena Anda menggunakan 'xargs', ini akan menampilkannya sebagai satu baris. Jadi, Anda akan mendapatkan "1,2 3".

Pembatas digunakan untuk pemisahan. Saya menggunakan karakter /. Satu trik yang menarik: Anda dapat mengganti pembatas dengan sebagian besar karakter lain, selama kami menyimpannya dalam format yang sama di antara tanda kutip. Jadi ini akan berhasil juga ....

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

atau

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

Jelas, menggunakan karakter tertentu sebagai pembatas bisa membingungkan, jadi cerdaslah.

Michael Bruce
sumber
0
xargs <k.txt | tr \  \|

Anda tidak perlu cat- hanya lulus dalam file input dan - jika diberikan perintah tidak lain - xargsakan pingsan format default - yang merupakan satu jenis dengan /bin/echo's (tanpa interpretasi backslash c-escape) .

xargsakan menghapus spasi putih kepala / ekor dari file input dan menekan urutan spasi putih lainnya ke satu ruang. Ini berarti bahwa sementara lewat file dari trke xargsseperti:

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

... mencetak ...

1|2|3|

... pergi ke arah lain dan hanya beroperasi pada argumen bahwa batasanxargs ruang tidak ....

1|2|3\n

... karena xargsmencetak baris akhir baris terakhir (seperti yang diperlukan untuk file teks) , tetapi tidak mendapatkan trpenjelasan seperti itu.

Perhatikan, bagaimanapun, bahwa ini (atau solusi lain yang ditawarkan di sini) tidak diperhitungkan untuk xargsmengutip input. xargsakan membagikan karakter spasi whitespace non-baris tunggal / ganda / backslash yang dikutip dalam input, yang dapat dikutip seperti:

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

1 2      3' '4
mikeserv
sumber