รับองค์ประกอบหนึ่งของสตริงพา ธ โดยใช้ bash


9

ฉันมีไฟล์ ASCII ที่มีไฟล์พา ธ ที่ฉันอ่านโดยใช้:

while read p; do echo $p; done < filelist.txt

ไฟล์มี filepaths ที่มีรูปแบบต่อไปนี้:

./first/example1/path
./second/example1/path
./third/example2/path

ฉันจะรับส่วนเฉพาะของสตริงพา ธ (จาก/ไปยัง/) ได้เช่นฉันต้องได้รับผลลัพธ์ที่พิมพ์:

first
second
third

และนอกจากนี้ยังมี

example1
example1
example2

ฉันแน่ใจว่ามีวิธีการทำเช่นนี้โดยใช้การแสดงออกปกติและsedแต่ฉันไม่คุ้นเคยกับมัน

คำตอบ:


17

การใช้cut:

$ cat filelist.txt
./first/example1/path
./second/example1/path
./third/example2/path

$ cut -d/ -f2 filelist.txt 
first
second
third

$ cut -d/ -f3 filelist.txt 
example1
example1
example2

การ-d/ตั้งค่าตัวคั่นคอลัมน์เป็น/และ-f2เลือกคอลัมน์ที่ 2

แน่นอนคุณสามารถใช้ตัวแปร Bash แทนชื่อไฟล์หรือข้อมูลไพพ์ลงในcutคำสั่ง:

cut -d/ -f3 $MyVariable
echo ./another/example/path | cut -d/ -f3

ใช้| cut -d/ -f3 ในท่อได้หลอกลวง ขอบคุณ! นี่คือคำสั่งแบบเต็มตอนนี้: while read p; do echo $p; done < filelist.txt | cut -d/ -f3
mcExchange

3
@mcExchange ไม่มีเหตุผลที่จะใช้ในขณะที่ลูป มันง่ายกว่าที่จะทำ cut -d/ -f3 filelist.txt
Monty Harder

1
นอกจากนี้การหลีกเลี่ยงในขณะที่หลีกเลี่ยงปัญหาการอ้างอิงและจะไม่ล้มเหลวกับการขึ้นบรรทัดใหม่ในชื่อไฟล์
Volker Siegel

10

คุณสามารถทำได้โดยตรงในreadคำสั่งของคุณโดยใช้IFSตัวแปรเช่น

$ while IFS=/ read -r p1 p2 p3 r; do echo "$p2"; done < filelist.txt 
first
second
third

5

คุณสามารถใช้ได้ awk

pilot6@Pilot6:~$ cat filelist.txt
./first/example1/path
./second/example1/path
./third/example2/path

pilot6@Pilot6:~$ awk -F "/" '{print $2}' filelist.txt
first
second
third

pilot6@Pilot6:~$ awk -F "/" '{print $3}' filelist.txt
example1
example1
example2

3

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

$> echo ${FILE//\//\ }                                                         
sys class backlight intel_backlight brightness
$> ARRAY=( ${FILE//\//" " } )                                                  
$> echo ${ARRAY[2]}
backlight

$> FILE="./dir1/dir2/file.txt"                                                 
$> ARRAY=( ${FILE//\/" "} )
$> echo ${ARRAY[@]}                                                            
. dir1 dir2 file.txt
$> echo ${ARRAY[1]}
dir1

ตอนนี้เรามีรายการที่สร้างขึ้นจากเส้นทาง IFSโปรดทราบว่าถ้าเส้นทางประกอบด้วยช่องว่างมันอาจเกี่ยวข้องกับการเปลี่ยนแปลงคั่นข้อมูลภายใน


1

ทุบตีและcutเป็นวิธีที่จะไปอย่างไรก็ตามทางเลือกโดยใช้ Perl:

perl -F/ -lane 'print(@F[1])' filelist.txt

สำหรับ/เขตข้อมูล -d เขตที่สองและ

perl -F/ -lane 'print(@F[2])' filelist.txt

สำหรับ/ฟิลด์ที่ถูก จำกัดที่สาม

  • -l: เปิดใช้งานการประมวลผลโดยอัตโนมัติ มันมีเอฟเฟกต์สองแบบแยกกัน ก่อนอื่นมันจะ chomps $ / (ตัวคั่นเร็กคอร์ดอินพุต) โดยอัตโนมัติเมื่อใช้กับ -n หรือ -p ประการที่สองมันกำหนด $ \ (ตัวคั่นเร็กคอร์ดเอาท์พุท) ให้มีค่าของ octnum เพื่อให้คำสั่งการพิมพ์ใด ๆ จะมีตัวคั่นนั้นเพิ่มกลับมา หากไม่ระบุ octnum ให้ตั้งค่า $ \ เป็นค่าปัจจุบันของ $ /
  • -a: เปิดโหมด autosplit เมื่อใช้กับ -n หรือ -p คำสั่ง split โดยปริยายไปยังอาร์เรย์ @F นั้นทำขึ้นเป็นสิ่งแรกภายใน implicit ขณะที่ loop สร้างโดย -n หรือ -p
  • -n: ทำให้ Perl ถือว่าวนรอบต่อไปนี้รอบโปรแกรมของคุณ, ซึ่งทำให้วนซ้ำอาร์กิวเมนต์ของชื่อไฟล์ค่อนข้างจะเหมือนกับ sed -n หรือ awk:

    LINE:
      while (<>) {
          ...             # your program goes here
      }
  • -e: อาจใช้เพื่อป้อนโปรแกรมหนึ่งบรรทัด;

  • print(@F[N]): พิมพ์ฟิลด์ Nth
% cat filelist.txt 
./first/example1/path
./second/example1/path
./third/example2/path
% perl -F/ -lane 'print(@F[1])' filelist.txt
first
second
third
% perl -F/ -lane 'print(@F[2])' filelist.txt
example1
example1
example2
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.