Wyodrębnij nazwę pliku ze ścieżki w programie awk

21

Mam skrypt awk i przekazałem mu plik CSV.

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

To, co robię, to uzyskanie FILENAME wewnątrz script.awk. FILENAME daje mi całą ścieżkę. Ponieważ jestem w awk, nie mogę używać basename FILENAME.

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

Próbowałem z tym w środku script.awk

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

ale nie mogę tego wykonać wewnątrz script.awk. Jak mogę dostać się asgd.csvdo programu awk?

Aashu
źródło

Odpowiedzi:

33

Kilka opcji:

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

Lub:

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

Zauważ, że te implementacje basenamepowinny działać w typowych przypadkach, ale nie w przypadkach narożnych, takich jak basename /path/to/x///zwracanie pustego ciągu zamiast xlub /gdzie zwracanie pustego ciągu zamiast /, chociaż w przypadku zwykłych plików, to nie powinno się zdarzyć.

Pierwszy nie będzie działał poprawnie, jeśli ścieżki plików (do ostatnich /) zawierają sekwencje bajtów, które nie tworzą prawidłowych znaków w bieżących ustawieniach narodowych (zazwyczaj taka sytuacja ma miejsce w ustawieniach regionalnych UTF-8 z nazwami plików zakodowanymi w około 8 zestaw znaków jednobajtowych). Można obejść ten problem, ustawiając ustawienia regionalne na C, gdzie każda sekwencja bajtów tworzy prawidłowe znaki.

Stéphane Chazelas
źródło
5
Jeśli potrzebujesz kodu, który będzie działał łatwo w istniejącym skrypcie awk bez wprowadzania funkcji, należy użyć: n = split(FILENAME, a, "/"); basename=a[n];. Nie używaj, subponieważ zmieni to FILENAMEzmienną (co nie jest problemem z funkcją, ponieważ awk używa wywołania według wartości).
shiri,
10

Wypróbuj ten awk one-liner,

$ awk 'END{ var=FILENAME; split (var,a,/\//); print a[5]}' /home/abc/imp/asgd.csv
asgd.csv
Avinash Raj
źródło
3
lubawk 'END{ var=FILENAME; n=split (var,a,/\//); print a[n]}' /home/abc/imp/asgd.csv
Avinash Raj
0

najlepszym sposobem na wyeksportowanie go z wejściowego pliku CSV lub bezpośrednio ze ścieżki pliku wejściowego, możesz go odwrócić, a następnie uzyskać 1 kolumnę, a następnie ponownie odwrócić.

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

lub po prostu

echo $FileNamePath| rev | awk -v FS='/' '{print $1}' | rev 
FariZ
źródło
0

Użyj funkcji podziału Awk

Jednym ze sposobów jest skorzystanie z funkcji podziału. Na przykład:

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

Działa to nawet na wielu plikach. Na przykład:

$ awk '{idx = split(FILENAME, parts, "/"); print parts[idx]; nextfile}' \
      /etc/passwd /etc/group
passwd
group
CodeGnome
źródło
0

Na systemach, gdzie basenamepolecenie jest dostępne, można było użyć awk„s system()funkcję lub expression | getline varstrukturę zadzwonić zewnętrznego basenamepolecenia. Może to pomóc w rozliczeniu przypadków narożnych wymienionych w odpowiedzi Stephane'a .

$ awk '{cmd=sprintf("basename %s",FILENAME);cmd | getline out; print FILENAME,out; exit}' /etc///passwd
/etc///passwd passwd
Sergiy Kolodyazhnyy
źródło