รายการในสคริปต์เชลล์ทุบตี

ฉันทำสคริปต์นี้

#!/bin/bash

liste=`ls -l`
for i in $liste
do
    echo $i
done

ปัญหาคือฉันต้องการให้สคริปต์แสดงผลลัพธ์แต่ละบรรทัดทีละบรรทัด แต่แสดงคำต่อคำ:

ฉันมี :

my_name
etud 
4096
Oct
8
10:13

และฉันต้องการที่จะมี:

my_name etud 4096 Oct 8 10:13

จุดมุ่งหมายสุดท้ายของสคริปต์คือการวิเคราะห์แต่ละบรรทัด จึงเป็นเหตุผลที่ผมอยากสามารถกู้คืนทั้งบรรทัดได้ บางทีรายการอาจไม่ใช่ทางออกที่ดีที่สุด แต่ฉันไม่รู้วิธีกู้คืนบรรทัด


person federem    schedule 10.10.2013    source แหล่งที่มา
comment
เป็นไปได้ที่ซ้ำกันของ คุณจะประมวลผลผลลัพธ์ของคำสั่งในเชลล์ทีละบรรทัดได้อย่างไร   -  person Mark Reed    schedule 10.10.2013
comment
@federem ทำไมคุณไม่บอกเราว่าคุณต้องการข้อมูล เฉพาะ ใดบ้าง ประทับเวลา? ขนาด? มีวิธีที่ดีกว่าในการรับสิ่งเหล่านั้น โดยไม่เกี่ยวข้องกับ ls   -  person Charles Duffy    schedule 11.10.2013


คำตอบ (5)


ในการเริ่มต้น เราจะถือว่าไม่มีชื่อไฟล์ใดของคุณที่มีการขึ้นบรรทัดใหม่:

ls -l | IFS= while read -r line; do
    echo "$line"
    # Do whatever else you want with $line
done

หากชื่อไฟล์ของคุณ สามารถ มีการขึ้นบรรทัดใหม่ สิ่งต่างๆ อาจยุ่งยาก ในกรณีนี้ จะดีกว่า (แม้ว่าจะช้ากว่า) ที่จะใช้ stat เพื่อดึงข้อมูลเมตาที่ต้องการจากแต่ละไฟล์ทีละไฟล์ ปรึกษา man stat เพื่อดูรายละเอียดเกี่ยวกับวิธีการทำงานของ stat ในท้องถิ่นของคุณ เนื่องจากไม่ได้มาตรฐานมากนัก

for f in *; do
    line=$(stat -c "%U %n %s %y" "$f")  # One possibility
    # Work with $line as if it came from ls -l
done
person chepner    schedule 10.10.2013
comment
จริง. หากคุณยังคงต้องเรียกใช้กระบวนการใหม่สำหรับแต่ละไฟล์ การควบคุมเอาต์พุตที่ stat อนุญาตอาจสะดวกกว่า (แต่ใช่ ฉันมองข้ามไปว่าคุณสามารถเรียก ls สำหรับแต่ละไฟล์ได้) - person chepner; 11.10.2013

คุณสามารถแทนที่ได้

echo $i

กับ

echo -n "$i "

echo -n ส่งออกไปยังคอนโซลโดยไม่ต้องขึ้นบรรทัดใหม่

person Fabrice Jammes    schedule 10.10.2013
comment
echo -n ไม่ใช่มาตรฐาน POSIX printf เป็นแนวทางที่ปลอดภัยและพกพาได้ - person Charles Duffy; 10.10.2013
comment
@Charles Duffy มันถูกกำหนดไว้ใน IEEE Std 1003.1-2001 POSIX - person Jim Black; 10.10.2013
comment
@JimBlack เป็นส่วนขยาย XSI เท่านั้น - person Charles Duffy; 11.10.2013
comment
@JimBlack คำพูด: System V echo ไม่รองรับตัวเลือกใด ๆ แต่อนุญาตให้ใช้ลำดับการหลีกภายในตัวถูกดำเนินการ ตามที่อธิบายไว้สำหรับการใช้งาน XSI ในส่วน OPERANDS คำพูดอื่น: เป็นไปไม่ได้ที่จะใช้ echo แบบพกพาในทุกระบบ POSIX เว้นแต่จะละเว้นทั้ง -n (เป็นอาร์กิวเมนต์แรก) และลำดับการหลีกเลี่ยง - person Charles Duffy; 11.10.2013

อีกอย่างที่ต้องทำแบบ while loop และไม่มีไปป์:

#!/bin/bash

while read line
do
    echo "line: $line"
done < <(ls -l)
person Labynocle    schedule 10.10.2013
comment
สิ่งนี้ถูกต้อง (ยกเว้นการใช้ read ที่ไม่มี -r -- ดังนั้น มีการตีความลำดับหลีก -- และปล่อยให้ $IFS เป็นค่าเริ่มต้น -- และทำให้มีช่องว่างต่อท้ายถูกลบออก) หากเป้าหมายคือการสาธิตการอ่านจากสตรีม มันไม่ถูกต้อง หากเป้าหมายคือการสาธิตการอ่านรายการไฟล์ (บางคนคิดว่า ls เป็นวิธีที่ถูกต้องในการทำเช่นนี้!) คงจะดีถ้าคำตอบชัดเจนยิ่งขึ้น - person Charles Duffy; 10.10.2013

ก่อนอื่น ฉันหวังว่าคุณจะไม่ได้ใช้ ls ในโค้ดจริงของคุณจริงๆ แต่เพียงใช้เป็นตัวอย่างเท่านั้น หากคุณต้องการรายการไฟล์ ls เป็นเครื่องมือที่ไม่ถูกต้อง ดู http://mywiki.wooledge.org/ParsingLs สำหรับรายละเอียด

ประการที่สอง bash เวอร์ชันใหม่มีบิวด์อินชื่อ readarray

ลองสิ่งนี้:

readarray -t my_array < <(ls -l)
for entry in "${my_array[@]}"; do
  read -a pieces <<<"$entry"
  printf '<%s> ' "${pieces[@]}"; echo
done

ขั้นแรก สร้างอาร์เรย์ (เรียกว่า my_array) โดยมีเอาต์พุตทั้งหมดจากคำสั่งที่กำลังรันอยู่

จากนั้น สำหรับแต่ละบรรทัดในเอาต์พุตนั้น การสร้างอาร์เรย์ชื่อ pieces และส่งเสียงแต่ละส่วนโดยมีวงเล็บลูกศรล้อมรอบ

หากคุณต้องการอ่านทีละบรรทัด แทนที่จะอ่านทั้งไฟล์พร้อมกัน โปรดดูที่ http://mywiki.wooledge.org/BashFAQ/001 ("ฉันจะอ่านไฟล์ (สตรีมข้อมูล ตัวแปร) ทีละบรรทัด (และ/หรือฟิลด์ต่อฟิลด์) ได้อย่างไร?")

person Charles Duffy    schedule 10.10.2013
comment
<(ls -l) จะล้มเหลวในสถานการณ์เดียวกันกับ ls -l | while read... - person chepner; 10.10.2013
comment
@chepner หากความหมายของคุณ ls เฉพาะเจาะจงฉันไม่เชื่อว่าฉันเคยบอกเป็นนัยถึงสิ่งที่ตรงกันข้าม - ดูย่อหน้าแรกของคำตอบของฉัน (ที่กล่าวมา เว้นแต่คุณจะไม่พิจารณาที่จะสูญเสียสถานะกระบวนการท้องถิ่นที่เกี่ยวข้องกับเนื้อหาที่คุณอ่านว่าล้มเหลว ฉันไม่สามารถเห็นด้วยกับความถูกต้องของการคัดค้านในกรณีทั่วไปที่ไม่เฉพาะเจาะจง) - person Charles Duffy; 11.10.2013

การรวมคำตอบก่อนหน้าโดยจำเป็นต้องจัดเก็บรายการไฟล์ไว้ในตัวแปร คุณสามารถทำเช่นนี้ได้

echo -n "$list"|while read -r lin
do
 echo $lin
done
person FeLocci    schedule 10.10.2013