Obtenir le dernier champ en utilisant awk substr


99

J'essaye d'utiliser awkpour obtenir le nom d'un fichier étant donné le chemin absolu vers le fichier.
Par exemple, quand on /home/parent/child/filenameme donne le chemin d'entrée que je voudrais obtenir, filename j'ai essayé:

awk -F "/" '{print $5}' input

qui fonctionne parfaitement.
Cependant, je suis un codage en dur $5qui serait incorrect si mon entrée a la structure suivante:

/home/parent/child1/child2/filename

Une solution générique nécessite donc de toujours prendre le dernier champ (qui sera le nom du fichier).

Existe-t-il un moyen simple de faire cela avec la fonction awk substr?


2
comme quelqu'un l'a souligné, utiliser basenameest la façon officielle de le faire, utiliser awkpour cela n'est pas bon de le dire à la légère. : D
Kashyap

Réponses:


206

Utilisez le fait qui awkdivise les lignes en champs en fonction d'un séparateur de champ, que vous pouvez définir. Par conséquent, en définissant le séparateur de champ, /vous pouvez dire:

awk -F "/" '{print $NF}' input

comme se NFréfère au nombre de champs de l'enregistrement en cours, l'impression $NFsignifie l'impression du dernier.

Donc, étant donné un fichier comme celui-ci:

/home/parent/child1/child2/child3/filename
/home/parent/child1/child2/filename
/home/parent/child1/filename

Ce serait la sortie:

$ awk -F"/" '{print $NF}' file
filename
filename
filename

3
Cela fonctionne parfaitement. Je n'ai pas pensé à la variable $ NF. Merci pour votre réponse simple et efficace immédiate.
Mari

6
Pour l'avant-dernier, utilisez $(NF-1).
Itachi

1
J'écrivais un script pour fonctionner avec certaines commandes docker et cela a fait l'affaire. Merci!
Harlin

30

Dans ce cas, il vaut mieux utiliser basenameau lieu de awk:

 $ basename /home/parent/child1/child2/filename
 filename

4
@Mari FYI dirname fait le contraire et supprime le fichier et non le chemin.
Chris Seymour

5

Une autre option consiste à utiliser la bash substitution de paramètres .

$ foo="/home/parent/child/filename"
$ echo ${foo##*/}
filename
$ foo="/home/parent/child/child2/filename"
$ echo ${foo##*/}
filename

5

Si vous êtes ouvert à une solution Perl, en voici une similaire à la solution awk de fedorqui:

perl -F/ -lane 'print $F[-1]' input

-F/spécifie /que le séparateur de champ
$F[-1]est le dernier élément du @Ftableau autosplit


1
Merci. Cela m'a aidé à obtenir le dernier mais un champ. perl -F "/" -lane 'print $ F [-2]' entrée
riderchap

cela a fonctionné pour moi lors de la réception de l'entrée canalisée. Totalement oublié perl.
Christopher

3

Cela devrait être un commentaire à la réponse du nom de base, mais je n'ai pas assez de point.

Si vous n'utilisez pas de guillemets doubles, basename ne fonctionnera pas avec un chemin contenant un espace:

$ basename /home/foo/bar foo/bar.png
bar

ok avec guillemets ""

$ basename "/home/foo/bar foo/bar.png"
bar.png

exemple de fichier

$ cat a
/home/parent/child 1/child 2/child 3/filename1
/home/parent/child 1/child2/filename2
/home/parent/child1/filename3

$ while read b ; do basename "$b" ; done < a
filename1
filename2
filename3

3

Je sais que j'ai environ 3 ans de retard sur ce point, mais ... vous devriez envisager l'expansion des paramètres, elle est intégrée et plus rapide.

si votre entrée est dans un var, disons, $ var1, faites simplement ${var1##*/}. Regardez ci-dessous

$ var1='/home/parent/child1/filename'
$ echo ${var1##*/}
filename
$ var1='/home/parent/child1/child2/filename'
$ echo ${var1##*/}
filename
$ var1='/home/parent/child1/child2/child3/filename'
$ echo ${var1##*/}
filename

2

Comme 5 ans de retard, je sais, merci pour toutes les propositions, j'avais l'habitude de le faire de la manière suivante:

$ echo /home/parent/child1/child2/filename | rev | cut -d '/' -f1 | rev
filename

Heureux de constater qu'il y a de meilleures manières


-1

Vous pouvez aussi utiliser:

    sed -n 's/.*\/\([^\/]\{1,\}\)$/\1/p'

ou

    sed -n 's/.*\/\([^\/]*\)$/\1/p'

1
À ce stade, personne n'a voté pour cette réponse, probablement parce qu'elle est relativement fugace :)
Josip Rodin
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.