แตกชื่อไฟล์จากพา ธ ในโปรแกรม awk


21

ฉันมีสคริปต์ awk และฉันได้ส่งไฟล์ CSV ไปยังมัน

awk -f script.awk /home/abc/imp/asgd.csv

สิ่งที่ฉันทำคือการได้รับ FILENAME script.awkภายใน FILENAME ให้เส้นทางทั้งหมดแก่ฉัน ในฐานะที่ผมอยู่ใน awk basename FILENAMEฉันไม่สามารถใช้

print FILENAME;
/home/abc/imp/asgd.csv

ฉันได้ลองกับสิ่งนี้แล้ว script.awk

echo $FILENAME | awk -F"/" '{print $NF}'

script.awkแต่ฉันไม่สามารถดำเนินการนี้ภายใน ฉันจะเข้าasgd.csvสู่โปรแกรม awk ได้อย่างไร

คำตอบ:


33

หลายตัวเลือก:

awk '
  function basename(file) {
    sub(".*/", "", file)
    return file
  }
  {print FILENAME, basename(FILENAME)}' /path/to/file

หรือ:

awk '
  function basename(file, a, n) {
    n = split(file, a, "/")
    return a[n]
  }
  {print FILENAME, basename(FILENAME)}' /path/to/file

โปรดทราบว่าการใช้งานเหล่านั้นของbasenameควรทำงานสำหรับกรณีทั่วไป แต่ไม่ได้อยู่ในกรณีมุมเช่นbasename /path/to/x///ที่พวกเขากลับสตริงที่ว่างเปล่าแทนxหรือ/ที่พวกเขากลับสตริงที่ว่างเปล่าแทน/แต่สำหรับไฟล์ปกติที่ไม่ควรเกิดขึ้น

อันแรกจะไม่ทำงานอย่างถูกต้องหากเส้นทางของไฟล์ (ถึงสุดท้าย/) มีลำดับของไบต์ที่ไม่ได้สร้างตัวละครที่ถูกต้องในสถานที่ปัจจุบัน (โดยทั่วไปสิ่งนี้เกิดขึ้นในสถานที่ UTF-8 ที่มีชื่อไฟล์เข้ารหัสในบาง 8 ชุดอักขระไบต์เดี่ยวบิต) คุณสามารถแก้ไขได้โดยแก้ไขโลแคลเป็น C ซึ่งลำดับของอักขระแบบฟอร์มที่ถูกต้องทุกไบต์


5
หากคุณจำเป็นต้องใช้รหัสที่จะทำงานได้อย่างง่ายดายภายในสคริปต์ awk n = split(FILENAME, a, "/"); basename=a[n];ที่มีอยู่โดยไม่ต้องแนะนำฟังก์ชั่นที่คุณควรใช้: อย่าใช้subตามที่จะเปลี่ยนFILENAMEตัวแปรจริง(ซึ่งไม่ใช่ปัญหากับฟังก์ชั่นเนื่องจาก awk ใช้โทรตามค่า)
shiri

10

ลองอันนี้ awk หนึ่งซับ

$ awk 'END{ var=FILENAME; split (var,a,/\//); print a[5]}' /home/abc/imp/asgd.csv
asgd.csv

3
หรือawk 'END{ var=FILENAME; n=split (var,a,/\//); print a[n]}' /home/abc/imp/asgd.csv
Avinash Raj

0

วิธีที่ดีที่สุดในการส่งออกจากอินพุต CSV หรือโดยตรงจากพา ธ ไฟล์อินพุตคุณสามารถย้อนกลับได้จากนั้นรับ 1 คอลัมน์จากนั้นย้อนกลับอีกครั้ง

function getFileFromPath() {
    FileName=$1
    cat $FileName | while read Filename
    do
        echo $Filename| rev | awk -v FS='/' '{print $1}' | rev 
    done
}

หรือเพียงแค่

echo $FileNamePath| rev | awk -v FS='/' '{print $1}' | rev 

0

ใช้ฟังก์ชั่นแยกของ Awk

วิธีหนึ่งในการทำเช่นนี้คือการใช้ฟังก์ชั่นแยก ตัวอย่างเช่น:

awk '{idx = split(FILENAME, parts, "/"); print parts[idx]; nextfile}' /path/to/file

สิ่งนี้สามารถใช้งานได้กับหลายไฟล์ ตัวอย่างเช่น:

$ awk '{idx = split(FILENAME, parts, "/"); print parts[idx]; nextfile}' \
      /etc/passwd /etc/group
passwd
group

0

ในระบบที่basenameคำสั่งสามารถใช้ได้หนึ่งสามารถใช้awk's system()ฟังก์ชันหรือexpression | getline varโครงสร้างภายนอกที่จะเรียกbasenameคำสั่ง ความช่วยเหลือนี้สามารถบัญชีสำหรับกรณีมุมที่กล่าวถึงในคำตอบของสเตฟาน

$ awk '{cmd=sprintf("basename %s",FILENAME);cmd | getline out; print FILENAME,out; exit}' /etc///passwd
/etc///passwd passwd
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.