Extrahieren Sie den Dateinamen aus dem Pfad im awk-Programm

21

Ich habe ein awk-Skript und habe eine CSV-Datei an dieses übergeben.

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

Was ich tue, ist, FILENAME innerhalb zu erhalten script.awk. FILENAME gibt mir den ganzen Weg. Da ich in awk bin, kann ich nicht verwenden basename FILENAME.

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

Ich habe es innerhalb versucht script.awk

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

aber ich kann das nicht innerhalb ausführen script.awk. Wie komme ich asgd.csvin ein awk-Programm?

Aashu
quelle

Antworten:

33

Mehrere Möglichkeiten:

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

Oder:

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

Beachten Sie, dass diese Implementierungen von basenamefür die gängigen Fälle funktionieren sollten, jedoch nicht in Eckfällen, in basename /path/to/x///denen die leere Zeichenfolge zurückgegeben wird xoder in /denen die leere Zeichenfolge zurückgegeben wird /, obwohl dies bei regulären Dateien nicht vorkommen sollte.

Die erste Methode funktioniert nicht ordnungsgemäß, wenn die Dateipfade (bis zur letzten /) Folgen von Bytes enthalten, die im aktuellen Gebietsschema keine gültigen Zeichen bilden (in der Regel geschieht dies in UTF-8-Gebietsschemata mit in 8 codierten Dateinamen Bit Einzelbyte-Zeichensatz). Sie können das umgehen, indem Sie das Gebietsschema auf C setzen, wobei jede Bytefolge gültige Zeichen bildet.

Stéphane Chazelas
quelle
5
Wenn Sie Code benötigen , die ohne die Einführung einer Funktion leicht innerhalb eines bestehenden awk - Skript arbeiten, sollten Sie verwenden: n = split(FILENAME, a, "/"); basename=a[n];. Nicht verwenden, subda dies die FILENAMEVariable tatsächlich ändert (was für die Funktion kein Problem darstellt, da awk call by value verwendet).
Shiri
10

Versuchen Sie dieses awk Einzeiler,

$ awk 'END{ var=FILENAME; split (var,a,/\//); print a[5]}' /home/abc/imp/asgd.csv
asgd.csv
Avinash Raj
quelle
3
oderawk 'END{ var=FILENAME; n=split (var,a,/\//); print a[n]}' /home/abc/imp/asgd.csv
Avinash Raj
0

Am besten exportieren Sie es aus der Eingabe-CSV oder direkt aus dem Eingabedateipfad. Sie können es umkehren, dann 1 Spalte abrufen und dann erneut umkehren.

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

oder einfach

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

Verwenden Sie die Split-Funktion von Awk

Eine Möglichkeit, dies zu tun, ist die Verwendung der Split-Funktion. Beispielsweise:

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

Dies funktioniert sogar bei mehreren Dateien. Beispielsweise:

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

Auf den Systemen , in denen basenameBefehl verfügbar ist, könnte man verwenden awk‚s - system()Funktion oder expression | getline varStruktur außerhalb ruft basenameBefehl. Dies kann helfen, Eckfälle zu berücksichtigen, die in Stephanes Antwort erwähnt wurden .

$ awk '{cmd=sprintf("basename %s",FILENAME);cmd | getline out; print FILENAME,out; exit}' /etc///passwd
/etc///passwd passwd
Sergiy Kolodyazhnyy
quelle