แยกไฟล์ข้อความที่คั่นด้วยทุบตีเป็นข้อโต้แย้งคำสั่ง


10

ฉันมีไฟล์ข้อความแยกย่อยดังนี้:

field1,field2,field3 
xield1,xield2,xield3 
dield1,dield2,dield3 
gield1,gield2,gield3

แต่ละคอลัมน์เหล่านี้จะเป็นพารามิเตอร์ของโปรแกรมและฉันต้องการให้โปรแกรมถูกเรียกสำหรับแต่ละบรรทัด

ฉันหวังว่าจะวนซ้ำบางอย่างเช่น:

for $i in file
    command $field2 -x $field3 -PN -$field1 >> output
done

อะไรจะเป็นวิธีที่ดีที่สุดในการบรรลุสิ่งนี้ในทุบตี?


จำนวนของฟิลด์คงที่หรือไม่
โจเซฟอาร์

@JosephR ใช่พวกเขาคือเสมอ 3
Dean

คำตอบ:


7
while IFS=, read xx yy zz;do
    echo $xx $yy $zz
done < input_file

สิ่งนี้จะทำงานได้ถ้าจำนวนของฟิลด์คงที่ แทนที่จะechoใช้คำสั่งของคุณ


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

คุณหมายถึงความสำเร็จหรือล้มเหลว คำสั่งของคุณทำอะไร?
coffeMug

ฉันเดาว่าคำสั่งที่เขาเรียกใช้นั้นกำลังอ่านอินพุตมาตรฐานก่อนที่คำสั่ง "read" จะสามารถอ่านได้
plugwash

4

คุณควรใช้ a whileในreadตัว:

while IFS= read -r line;do
    fields=($(printf "%s" "$line"|cut -d',' --output-delimiter=' ' -f1-))
    command "${fields[1]}" -x "${fields[2]}" ... # ${fields[1]} is field 2
done < your_file_here

วิธีนี้ใช้ได้ผล

  • คำสั่งต้องใช้สายและแยกไว้บนตัวคั่นที่ระบุโดยcut-d
  • --output-delimiterเป็นตัวละครตัวคั่นที่จะใช้ในการแสดงฟิลด์ที่เลือกที่นี่เราเลือกพื้นที่เพื่อให้เราสามารถใส่เขตข้อมูลที่แตกต่างกันลงในอาร์เรย์cutfields
  • ในที่สุดเราต้องการเขตข้อมูลทั้งหมด (จากเขตข้อมูล 1 ถึงจุดสิ้นสุด) และนั่นคือสิ่งที่-f1-เข้ามาเล่น
  • ตอนนี้คุณมีฟิลด์ต่าง ๆ ที่เก็บอยู่ในตัวแปรอาเรfieldsย์คุณสามารถเข้าถึงฟิลด์ใด ๆ ที่คุณต้องการด้วยไวยากรณ์${field[number]}ซึ่งnumberน้อยกว่าหนึ่งหมายเลขฟิลด์จริงที่คุณต้องการเนื่องจากการทำดัชนีอาเรย์นั้นเป็นศูนย์ใน Bash

บันทึก

  • สิ่งนี้จะล้มเหลวหากฟิลด์ใด ๆ ของคุณมีช่องว่าง

สำหรับฟิลด์จำนวนคงที่

คุณสามารถทำสิ่งที่คล้ายกับคำตอบของ 1_CR แทน :

while IFS= read -r line;do
    IFS=, read -r field1 field2 field3 <<-EOI
    $line
    EOI
    command "$field2" -x "$field3" ... 
done < your_file_here

ข้างต้นในขณะที่ดูเหมือนว่ามีเสียงดังมากขึ้นควรทำงานในเปลือกที่สอดคล้องกับ POSIX ใด ๆ ไม่ได้เป็นเพียงทุบตี


มันไม่ได้อ่านในไฟล์ที่ฉันมีปัญหามันแยกบรรทัดออกเป็นคอลัมน์
Dean

@Dean Yeah ขอโทษ ฉันไม่ได้สนใจ ทำงานที่ตอนนี้
โจเซฟอาร์

@Dean โปรดดูคำตอบที่ปรับปรุงแล้ว ฉันจะเพิ่มคำอธิบายในไม่ช้า
Joseph R.

@JosephR. เป็นไปได้ที่จะหลีกเลี่ยงการใช้เครื่องมือภายนอกสำหรับการแยกโดยการตั้งค่าIFSเป็นค่าที่เหมาะสมในการreadเรียก
iruvar

@ 1_CR ฉันรู้ขอบคุณ ฉันเพิ่งไปถึงที่ :)
โจเซฟอาร์

1

คุณสามารถreadแยกแต่ละบรรทัดเป็นอาร์เรย์บนได้,โดยตั้งค่าIFSอย่างเหมาะสม

while IFS=, read -r -a input; do
 printf "%s\n" "${input[0]}" "${input[1]}"
done < input.txt

ดังนั้นในตัวอย่างข้างต้นคุณสามารถเข้าถึงแต่ละองค์ประกอบอาร์เรย์โดยใช้ดัชนีเริ่มต้น 0


1

นี้awkหนึ่งซับจะทำในสิ่งที่คุณต้องการ:

awk -F, '{cmd="echo " $2 " -x " $3 " -PN " $1 ">> output";  system(cmd)}' f.txt

แทนที่echoด้วยคำสั่งของคุณและf.txtด้วยไฟล์ที่คุณต้องการวนซ้ำ

คำอธิบายสั้น ๆ : -F,จะตั้ง,เป็นตัวคั่น cmdสร้างคำสั่งและsystem(cmd)เรียกคำสั่ง


1

สามารถใช้ gnu sed ได้เช่นกัน

sed infile -e 's!^\([^,]*\),\([^,]*\),\([^,]*\)$!command \1 -x \2 -PN \3!e' >> output

สังเกตการใช้ตัวเลือก e เพื่อคำสั่ง s

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