Estrai il nome del file dal percorso nel programma awk


21

Ho uno script awk e ho passato un file CSV ad esso.

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

Quello che sto facendo è ottenere FILENAME all'interno script.awk. FILENAME mi dà l'intero percorso. Come sono in awk non posso usare basename FILENAME.

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

Ho provato con questo dentro script.awk

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

ma non posso eseguirlo all'interno script.awk. Come posso entrare asgd.csvin un programma awk?

Risposte:


33

Diverse opzioni:

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

O:

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

Si noti che tali implementazioni di basenamedovrebbero funzionare per i casi comuni, ma non in casi angolari come quelli in basename /path/to/x///cui restituiscono la stringa vuota anziché xo in /cui restituiscono la stringa vuota anziché /, sebbene per i file normali, ciò non dovrebbe accadere.

Il primo non funzionerà correttamente se i percorsi dei file (fino all'ultimo /) contengono sequenze di byte che non formano caratteri validi nella locale corrente (in genere questo genere di cose accade in locali UTF-8 con nomi di file codificati in circa 8 bit set di caratteri a byte singolo). Puoi aggirare il problema fissando la locale su C dove ogni sequenza di byte forma caratteri validi.


5
Se avete bisogno di codice che funziona facilmente all'interno di uno script awk esistente senza introdurre una funzione, è necessario utilizzare: n = split(FILENAME, a, "/"); basename=a[n];. Non usare in subquanto cambierà effettivamente la FILENAMEvariabile (che non è un problema con la funzione poiché awk usa call per value).
Shiri,

10

Prova questo fantastico one-liner,

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

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

0

il modo migliore per esportarlo dall'input CSV o direttamente dal percorso del file di input è possibile invertirlo, quindi ottenere 1 colonna e quindi invertirlo nuovamente.

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

o semplicemente

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

0

Usa la funzione Split di Awk

Un modo per farlo è usare la funzione split. Per esempio:

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

Funziona anche su più file. Per esempio:

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

0

Sui sistemi in cui basenameè disponibile il comando, è possibile utilizzare awkla system()funzione o la expression | getline varstruttura per chiamare un basenamecomando esterno . Questo può aiutare a tenere conto dei casi angolari menzionati nella risposta di Stephane .

$ awk '{cmd=sprintf("basename %s",FILENAME);cmd | getline out; print FILENAME,out; exit}' /etc///passwd
/etc///passwd passwd
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.