จัดรูปแบบเอาต์พุตของ xargs


10

ฉันต้องการเปลี่ยนรูปแบบของเอาต์พุต xargs ที่แสดง

cat k.txt 
1 
2 
3 

และ

cat k.txt | xargs 
1 2 3

แต่ผมอยากจะมีหรือ1, 2, 3 1|2|3ข้อเสนอแนะใด ๆ


ที่จะประสบความสำเร็จกับสิ่งที่ (ไม่ได้ตรงนี้) เหมือนxargs cat -nแต่เป็นเรื่องง่ายถ้าคุณเพียงแค่ตัดตัวอักษรขึ้นบรรทัดใหม่นี้สามารถทำได้ด้วยecho $(cat), grepหรือawk(รวบรวมข้อมูลวิธีที่จะทำมัน) xargsไม่เหมาะกับวัตถุประสงค์ปัจจุบันของคุณ
41754

คำตอบ:


18

ด้านล่างนี้เป็นตัวอย่างหนึ่งโหลหรือหลายวิธีที่คุณสามารถใช้ไฟล์เช่นนี้:

$ cat k.txt
1
2
3

และแปลงเป็นรูปแบบนี้:

1,2,3

คุณสามารถใช้คำสั่งนี้เพื่อสร้างไฟล์ด้านบนหากคุณต้องการเล่น:

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

ตัวอย่างด้านล่างแบ่งออกเป็น 2 กลุ่ม คนที่ "ทำงาน" และคนที่ "เกือบ" ทำงาน ฉันออกไปเพราะบ่อยครั้งมันมีค่าพอที่จะดูว่าทำไมบางสิ่งบางอย่างไม่ทำงานเหมือนที่เห็นว่าทำไมบางสิ่งถึงทำ

ภาษาสคริปต์ส่วนใหญ่ที่ฉันคุ้นเคยเป็นตัวแทน บางตัวแสดงหลายครั้งเนื่องจากตัวย่อที่มีชื่อเสียงมักจะอ้างอิงใน Perl, TIMTOWTDI TIMTOWTDI

หมายเหตุ:คุณสามารถสลับเครื่องหมายจุลภาค ( ,) ในตัวอย่างด้านล่างและแทนที่ด้วยอักขระที่คุณต้องการเช่น|ในตัวอย่างด้านล่างและแทนที่ด้วยตัวอักษรสิ่งที่คุณต้องการคือ

ตัวอย่างที่ "ทำงาน"

ตัวอย่างโค้ดเหล่านี้จะสร้างผลลัพธ์ที่ต้องการ

pasteสั่ง:

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

sedสั่ง:

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

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

perlสั่ง:

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

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

awkสั่ง:

$ 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

pythonสั่ง:

$ 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's mapfileในตัว:

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

rubyสั่ง:

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

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

phpสั่ง:

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

คำเตือน

ตัวอย่างข้างต้นส่วนใหญ่จะใช้งานได้ดี บางคนมีปัญหาที่ซ่อนอยู่เช่นตัวอย่าง PHP ด้านบน ฟังก์ชั่นchop()เป็นนามแฝงจริงrtrim()ดังนั้นช่องว่างต่อท้ายของบรรทัดสุดท้ายก็จะถูกลบออก

ตัวอย่างทับทิมแรกก็เช่นกันและตัวอย่างงูหลามแรกก็เช่นกัน ปัญหาคือว่าพวกเขาใช้ประโยชน์จากประเภทของการดำเนินงานที่เป็นหลัก "สับ" ปิด, สุ่มสี่สุ่มห้า, อักขระต่อท้าย นี่เป็นสิ่งที่ดีสำหรับตัวอย่างที่ OP ให้มา แต่ต้องระมัดระวังเมื่อใช้ liners ชนิดหนึ่งเหล่านี้เพื่อให้แน่ใจว่าสอดคล้องกับข้อมูลที่พวกเขากำลังประมวลผล

ตัวอย่าง

พูดไฟล์ตัวอย่างของเราk.txtดูเป็นแบบนี้แทน:

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

มันดูคล้ายกัน แต่มีความแตกต่างเล็กน้อย ไม่มีการขึ้นบรรทัดใหม่ ( \n) เหมือนไฟล์ต้นฉบับ ตอนนี้เมื่อเราเรียกใช้ตัวอย่าง Python แรกเราจะได้รับ:

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

ตัวอย่างที่ "เกือบ" ทำงาน

เหล่านี้เป็น"เสมอเพื่อนเจ้าสาวไม่เคยเจ้าสาว"ตัวอย่าง ส่วนใหญ่สามารถปรับได้ แต่เมื่อทำงานเพื่อแก้ปัญหาที่อาจเกิดขึ้นเมื่อรู้สึกว่า "ถูกบังคับ" อาจเป็นเครื่องมือที่ผิดสำหรับงาน!

perlสั่ง:

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

trสั่ง:

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

cat+ echoคำสั่ง:

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

rubyสั่ง:

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

while+ readบิวด์อินของ Bash :

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

1
เกี่ยวกับawkฉันชอบทางเลือกที่สั้นกว่า:awk -vORS=, 1 k.txt
ทำงาน

ไม่แน่ใจว่า CentOS มีbash:mapfile -t a < k.txt; (IFS=','; echo "${a[*]}")
จัดการ

ไม่แน่ใจเกี่ยวกับบรรทัดใหม่ต่อท้าย จากการทดสอบของฉันperlและคุณawkก็มีพวกเขาเช่นกัน
จัดการ

ฉันจะใส่pasteหนึ่งที่ด้านบน นั่นคือสิ่งที่paste -sอยู่ตรงนี้ มันเป็นคำสั่งมาตรฐานและจะมีประสิทธิภาพมากที่สุด ส่วนอื่น ๆ ทั้งหมดเป็น overkill และ / หรือไม่พกพาหรือมีข้อ จำกัด
Stéphane Chazelas

mapfileค่อนข้างใหม่เพิ่มในbash4.0
จัดการ

4

@slm ได้รับคำตอบที่ดี แต่เป็นคำถามของคุณ "รูปแบบผลลัพธ์ของ xargs"

xargs -I{} echo -n "{}|" < test.txt
  • -I เป็นตัวเลือก "แทนที่สตริง"
  • {} เป็นตัวยึดสำหรับข้อความที่ส่งออก
  • สิ่งนี้คล้ายกับการใช้คู่วงเล็บปีกกาใน "ค้นหา"

หากคุณต้องการกำจัดร่องรอย|คุณสามารถใช้sedเพื่อทำความสะอาด:

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

นั่นเป็นการเพิ่มท่อเข้าไปหลังจาก 3 "1 | 2 | 3 |" ฉันได้รับปัญหาเดียวกันกับในขณะที่การแก้ปัญหาห่วงและ awk
slm

ใช่ถ้ามีบรรทัดใหม่ .. tr, sedและอื่น ๆ ยัง ..
ราหุล Patil

2

ฉันรู้ว่านี่เป็นกระทู้เก่า OP ถามด้วยรหัสง่ายๆเช่นนี้ เพื่อให้มันใกล้เคียงกับต้นฉบับฉันมีวิธีแก้ปัญหาง่ายๆ

cat k.txt | xargs
1 2 3

ใช้ sed

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

หรือ

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

sed สามารถดูแปลก ๆ เล็กน้อย แต่พังมันทำให้รู้สึกมาก

ใช้แทนสิ่งอื่นได้ g 'สำหรับโลก: หากไม่มีสิ่งนี้มันจะทำการทดแทนครั้งแรกในแต่ละบรรทัดใหม่ เนื่องจากคุณใช้ 'xargs' มันจะแสดงเป็นหนึ่งบรรทัด ดังนั้นคุณจะได้รับ "1,2 3"

ตัวคั่นใช้สำหรับการแยก ฉันใช้ / ตัวละคร เคล็ดลับที่น่าสนใจอย่างหนึ่ง: คุณสามารถแทนที่ตัวคั่นด้วยอักขระอื่น ๆ ส่วนใหญ่ตราบใดที่เรายังคงรูปแบบเดียวกันระหว่างเครื่องหมายคำพูด ดังนั้นมันจะทำงานได้เช่นกัน ....

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

หรือ

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

เห็นได้ชัดว่าการใช้ตัวอักษรบางตัวเป็นตัวคั่นอาจทำให้สับสนดังนั้นจึงต้องฉลาด


0
xargs <k.txt | tr \  \|

คุณไม่จำเป็นต้องcat- เพียงแค่ผ่านในการป้อนข้อมูลไฟล์และ - ถ้าได้รับไม่มีคำสั่งอื่น ๆ - xargsจะผ่านออกมารูปแบบเริ่มต้นของมัน - ซึ่งเป็นชนิดที่มี/bin/echo's (โดยไม่ต้องตีความทับขวาคหนี)

xargsจะตัดปิดช่องว่างส่วนหัว / ท้ายจากไฟล์อินพุตและบีบลำดับอื่นของช่องว่างลงไปที่ช่องว่างเดียว ซึ่งหมายความว่าในขณะที่ส่งไฟล์จากtrไปที่xargsชอบ:

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

... พิมพ์ ...

1|2|3|

... จะไปทางอื่นและการดำเนินงานเฉพาะในargsว่าxargsพื้นที่ delimits ไม่ ....

1|2|3\n

... เนื่องจากxargsพิมพ์บรรทัดใหม่ที่ตามมาสุดท้าย(ตามที่จำเป็นสำหรับไฟล์ข้อความ)แต่ไม่ได้รับการtrแก้ไขแบบนั้น

อย่างไรก็ตามโปรดทราบว่าสิ่งนี้(หรือโซลูชันอื่น ๆ ที่มีให้ที่นี่)ไม่ได้มีส่วนช่วยxargsในการอ้างอิงข้อความ xargsจะส่งผ่านตัวอักษรช่องว่าง whitespace แบบช่องเดี่ยว / คู่ / แบ็กสแลชที่ไม่ใช่ newline ซึ่งสามารถอ้างถึงได้เช่น:

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

1 2      3' '4
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.