Trích xuất tên tệp từ đường dẫn trong chương trình awk


21

Tôi có một tập lệnh awk và tôi đã chuyển một tập tin CSV cho nó.

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

Tôi đang làm gì để có được FILENAME trong script.awk. FILENAME cho tôi toàn bộ con đường. Khi tôi ở awk tôi không thể sử dụng basename FILENAME.

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

Tôi đã thử với điều này trong script.awk

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

nhưng tôi không thể thực hiện điều này trong vòng script.awk. Làm thế nào tôi có thể nhận được asgd.csvtrong một chương trình awk?

Câu trả lời:


33

Một vài lựa chọn:

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

Hoặc là:

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

Lưu ý rằng các triển khai đó basenamenên hoạt động cho các trường hợp phổ biến, nhưng không phải trong các trường hợp góc như basename /path/to/x///nơi chúng trả về chuỗi trống thay vì xhoặc /nơi chúng trả về chuỗi trống thay vì /, mặc dù đối với các tệp thông thường, điều đó không nên xảy ra.

Cái đầu tiên sẽ không hoạt động đúng nếu các đường dẫn tệp (cho đến cuối cùng /) chứa các chuỗi byte không tạo thành các ký tự hợp lệ trong miền địa phương hiện tại (thông thường loại này xảy ra ở các vị trí UTF-8 với tên tệp được mã hóa trong một số 8 bộ ký tự byte đơn bit). Bạn có thể giải quyết vấn đề đó bằng cách sửa miền địa phương thành C trong đó mỗi chuỗi ký tự byte hợp lệ.


5
Nếu bạn cần mã sẽ hoạt động dễ dàng trong tập lệnh awk hiện có mà không cần giới thiệu hàm, bạn nên sử dụng : n = split(FILENAME, a, "/"); basename=a[n];. Đừng sử dụng subvì điều đó thực sự sẽ thay đổi FILENAMEbiến số (đây không phải là vấn đề với hàm vì awk sử dụng lệnh gọi theo giá trị).
shiri

10

Hãy thử awk one-liner này,

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

3
hoặcawk 'END{ var=FILENAME; n=split (var,a,/\//); print a[n]}' /home/abc/imp/asgd.csv
Avinash Raj

0

cách tốt nhất để xuất nó từ CSV đầu vào hoặc trực tiếp từ đường dẫn tệp đầu vào, bạn có thể đảo ngược nó, sau đó lấy 1 cột và sau đó đảo ngược lại.

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

hoặc đơn giản

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

0

Sử dụng chức năng phân chia của Awk

Một cách để làm điều này là sử dụng chức năng phân chia. Ví dụ:

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

Điều này thậm chí hoạt động trên nhiều tập tin. Ví dụ:

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

0

Trên các hệ thống mà basenamelệnh có sẵn, người ta có thể sử dụng awk's system()chức năng hoặc expression | getline varcấu trúc để gọi bên ngoài basenamelệnh. Điều này có thể giúp tính toán cho các trường hợp góc được đề cập trong câu trả lời của Stephane .

$ awk '{cmd=sprintf("basename %s",FILENAME);cmd | getline out; print FILENAME,out; exit}' /etc///passwd
/etc///passwd passwd
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.