Xargs çıktısını biçimlendir


10

Çıkış xargs ekranlarının biçimini değiştirmek istiyorum

cat k.txt 
1 
2 
3 

Ve

cat k.txt | xargs 
1 2 3

Ancak istiyorum 1, 2, 3ya 1|2|3. Herhangi bir öneri?


Yani böyle (tam olarak değil bu) bir şeyle elde edilebilir xargs cat -n, ama sadece yeni satır karakterlerini Döşeme eğer daha kolaydır, bununla elde edilebilir echo $(cat), grepya da awk(tarama Bunu yapmanın yolu). xargsmevcut amacınıza iyi uymuyor.
41754

Yanıtlar:


18

Aşağıda, bunun gibi bir dosyayı nasıl alabileceğinize dair bir düzine örnek bulunmaktadır:

$ cat k.txt
1
2
3

ve bu biçime dönüştürün:

1,2,3

Birlikte çalmak istiyorsanız yukarıdaki dosyayı oluşturmak için bu komutu kullanabilirsiniz:

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

Aşağıdaki örnekler 2 gruba ayrılmıştır. "Çalışanlar" ve "neredeyse" olanlar. Bunlardan ayrılıyorum çünkü çoğu zaman bir şeyin neden işe yaramadığını görmek, bir şeyin neden işe yaradığını görmek kadar değerlidir.

Bildiğim çoğu komut dosyası dili temsil edilmektedir. Bazıları birden çok kez temsil edilir, çünkü tipik olarak Perl, TIMTOWTDI'da atıfta bulunulan ünlü kısaltmada olduğu gibi .

NOT:, Aşağıdaki örneklerde virgül ( ) değiştirebilir ve istediğiniz karakterlerle değiştirebilirsiniz |.

"Çalışan" örnekler

Bu kod parçacıkları istenen çıktıyı üretecektir.

pastekomut:

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

sedkomut:

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

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

perlkomut:

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

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

awkkomut:

$ 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

pythonkomut:

$ 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'in mapfileyerleşik:

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

rubykomut:

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

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

phpkomut:

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

Uyarılar

Yukarıdaki örneklerin çoğu işe yarayacaktır. Bazılarının yukarıdaki PHP örneği gibi gizli sorunları vardır. İşlev chop()aslında bir takma addır rtrim(), bu nedenle son satırın sondaki boşlukları da kaldırılır.

İlk Ruby örneği ve ilk Python örneği de öyle. Sorun, hepsinin, körü körüne bir izleyen karakteri "kesen" bir işlemden nasıl yararlandıklarıdır. Bu, OP'nin sağladığı örnek için iyidir, ancak bu tür bir astar kullanılırken, işledikleri verilere uygun olduklarından emin olmak için dikkat edilmelidir.

Misal

Örnek dosyamızı söyle, k.txtbunun yerine şöyle görünüyordu:

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

Benzer görünüyor ama ufak bir farkı var. \nOrijinal dosya gibi bir satırsonu ( ) yoktur. Şimdi ilk Python örneğini çalıştırdığımızda şunu elde ederiz:

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

"Neredeyse" çalışan örnekler

Bunlar "her zaman nedime, asla gelin" örnekleridir. Çoğu muhtemelen uyarlanabilir, ancak bir probleme potansiyel bir çözüm çalışırken, "zorla" hissettirdiğinde, muhtemelen iş için yanlış araçtır!

perlkomut:

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

trkomut:

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

cat+ echoKomutları:

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

rubykomut:

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

Bash while+ readyerleşikleri:

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

1
İlgili awkdaha kısa bir alternatif tercih:awk -vORS=, 1 k.txt
manatwork

bashmapfile -t a < k.txt; (IFS=','; echo "${a[*]}")
CentOS'un

son satırdan emin değilim. Benim testime göre perlve ilk awkonları da var.
manatwork

Onu pastetepeye koyardım. Tam olarak paste -sburada olan bu. Bu standart bir komut ve en verimli yöntem olurdu. Diğerlerinin hepsi aşırı kilolu ve / veya taşınabilir değil veya sınırlamaları var.
Stéphane Chazelas

mapfilebash4.0'da eklenen nispeten yenidir .
manatwork

4

@slm zaten güzel bir cevap verdi, ama sorunuz olarak "xargs format çıktısı"

xargs -I{} echo -n "{}|" < test.txt
  • -I "dizeleri değiştir" seçeneğidir.
  • {} çıktı metni için bir yer tutucudur.
  • Bu, "find" öğesinde kıvırcık parantez çiftinin kullanımına benzer.

Eğer sondan kurtulmak |istiyorsanız, sedbiraz temizlik yapmak için kullanabilirsiniz :

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

Bu, 3'ten sonra fazladan bir boru tutturur. Bir while döngüsü ve awk çözümü ile aynı sorunu yaşıyorum.
slm

evet, yeni bir satır .. varsa tr, sedaynı zamanda .. ve diğer
Rahul Patil

2

Bu eski bir konu, biliyorum. OP böyle basit bir kodla sordu. Orijinaline yakın tutmak için basit bir çözümüm var.

cat k.txt | xargs
1 2 3

sed kullan

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

veya

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

sed biraz garip görünebilir ama parçalanmış, çok mantıklı.

yerine koymak içindir. g 'global içindir: bu olmadan, her yeni satırda sadece ilk oyuncu değişikliği yapılır. 'Xargs' kullandığınız için bunları tek satır olarak görüntüler. Böylece "1,2 3" elde edersiniz.

Ayırıcı ayırma için kullanılır. / Karakterini kullandım. İlginç bir hile: tırnak işaretleri arasında aynı formatta kaldığımız sürece sınırlayıcıyı diğer birçok karakterle değiştirebilirsiniz. Bu da işe yarar ....

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

veya

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

Açıkçası, belirli karakterleri sınırlayıcı olarak kullanmak kafa karıştırıcı olabilir, bu yüzden akıllı olun.


0
xargs <k.txt | tr \  \|

İhtiyacınız yoktur cat- sadece dosya girişini iletin ve - başka bir komut verilmezse - xargsvarsayılan biçimini geçmeyecektir - /bin/echo's (ters eğik çizgi c-escape yorumları olmadan) .

xargsgiriş dosyasından baş / kuyruk boşluğunu sıyırır ve diğer boşluk alanlarını tek bir boşluğa sıkıştırır. Bu araçlar bu dosyayı geçerken triçin xargsbenzer:

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

... baskılar ...

1|2|3|

... gidiş başka bir yol ve sadece işletim args o xargsuzay-sınırlandırır yapar ....

1|2|3\n

... çünkü xargsson satırsonu satırını yazdırır (bir metin dosyası için gerektiği gibi) , ancak trbu şekilde ansile edilmez.

Bununla birlikte, bunun (veya burada sunulan başka bir çözümün)xargs girdide teklif vermediğini unutmayın . xargsgirişte kelimenin tam anlamıyla tek / çift / ters eğik çizgi alıntılı yeni satır olmayan boşluk karakterlerini iletir ve bunlar şu şekilde alıntılanabilir:

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

1 2      3' '4
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.