web-dev-qa-db-fra.com

Obtenir le dernier champ en utilisant awk substr

J'ai une simple exigence comme suit,
Je reçois les noms de fichiers avec le répertoire absolu.
Par exemple /home/parent/child/filename
Mon exigence est de supprimer le nom de fichier.
Ce que j'ai essayé, c'est:

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

qui fonctionne parfaitement.
Mais voici un codage difficile $5 qui peut différer si mon entrée a la structure suivante:

/home/parent/child1/child2/filename

Donc, il devrait être dynamique sans codage dur. Voici la logique:
Toujours prendre le dernier champ qui sera le nom du fichier (il faut donc vérifier à partir de l’inverse).

Quelqu'un peut-il m'aider avec la fonction awk substr ou toute autre fonction?

79
Mari

Utilisez le fait que awk divise les lignes dans les 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 sur /, vous pouvez dire:

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

comme NF fait référence au nombre de champs de l’enregistrement en cours, l’impression $NF signifie 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
170
fedorqui

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

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

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

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

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

5
Chris Koknat

Une autre option consiste à utiliser bashsubstitution de paramètre .

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

Cela devrait être un commentaire sur 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 les chemins où il y a un caractère d'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
Pierre-Damien

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

si votre entrée est dans une var, disons $ var1, faites juste ${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
3
Adriano_epifas

Comme 5 ans de retard, je sais, merci pour toutes les propositions, je le faisais de la manière suivante:

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

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

2
Nicko Glayre