J'essaie d'écrire un script shell qui devra transformer l'entrée de la forme suivante:
lines.each { |s| s.split('/')[2..-1].join('-').split('.')[0] }
En:
cut -d '/' -f x
C'est à dire diviser sur '/', supprimer les 2 premiers segments, supprimer le '.txt' et remplacer les barres obliques restantes par des tirets.
La substitution semble assez simple en utilisant tr:
paths=$(cat <<- EOF foo/bar/baz/qux.txt bar/baz/quz.txt baz/quz/foo.txt EOF ) echo $paths | tr '/' '-' | tr '.txt' ' '
6 Réponses :
Cela peut être fait en utilisant bash
extensions de paramètres :
baz-qux quz foo
Donne:
for name in foo/bar/baz/qux.txt bar/baz/quz.txt baz/quz/foo.txt; do new=${name#*/} # drop the shortest prefix match for */, thus everything up to first / new=${new#*/} # repeat, dropping the second segment new=${new%.txt} # drop shortest suffix match for .txt new=${new//\//-} # convert any remaining slashes echo "$new" done
Ce sont toutes des constructions intégrées du shell bash
, donc pas de processus externes comme cut
, sed
ou tr
requis.
Accepteriez-vous une modification déplaçant les commentaires vers un formulaire en ligne, pour éviter que le code ne paraisse plus long qu’il ne l’est?
Bien sûr @CharlesDuffy. J'avais envisagé de mettre la viande dans une fonction, ce que je ferais probablement si le code était pour moi.
Compte tenu de la première ligne de l'exemple d'entrée, je pense que new = $ {name ## * /}; new = $ {new% .txt}
serait tout ce qui est nécessaire? Bonne chance à tous.
Se sentir dense - ne pas voir où le dernier /
restant est changé en -
.
@PaulHodges le gars qui a édité a probablement manqué cette ligne: new = $ {new // \ // -} Je l'ai copiée pour un test local dans la première version de l'article
Y a-t-il une raison de ne pas utiliser new = $ {name # * / * /}
au lieu de deux extensions?
Vous pouvez essayer quelque chose comme ceci: cut -d / -f3- | couper -d. -f1 | tr / -
Explication:
cut -d / -f3-
- fractionné sur '/', et conserver le troisième champ et tout ce qui suit ( baz / qux.txt
) li >
coupe -d. -f1
- fractionné sur '.', conserve la première valeur (supprime l'extension de fichier) ( baz / qux
) tr / -
- Transforme tout "/" restant en "-".
( baz-qux
) Conceptuellement simple, mais la mise en place de trois processus distincts représente beaucoup de frais généraux.
Vous pouvez tout faire en une seule commande sed
sed -E 's|([^/]*/){,2}||; s|/|-|g; s|\.txt$||' file
Remplacez \ .txt $
par \. [^. ] $
pour supprimer toutes les extensions au lieu de seulement .txt
.
Ce sera la meilleure approche si le traitement d'un grand nombre d'entrées en une seule exécution (suffisamment pour surmonter les coûts de démarrage en temps constant de sed
avec ses E / S plus rapides une fois en cours d'exécution), ou cdarke si c'est un nombre plus petit.
Essayez Perl
$ cat mark_smith.txt foo/bar/baz/qux.txt bar/baz/quz.txt baz/quz/foo.txt $ perl -F"/" -lane ' @a=@F[2..$#F]; @b=map{s/.txt//g;$_} @a; print join("-",@b) ' mark_smith.txt baz-qux quz foo $
en supposant que .
est uniquement dans les noms de fichiers
$ awk -F[/.] '{n=NF; p=$(n-1)} n>4{p=$(n-2)"-"p} {print p}' file baz-qux quz foo
awk '{gsub(/^.{8}|.txt$/,"")sub(/\//,"-")}1' file baz-qux quz foo
La commande
tr '.txt' ''
ne fait pas ce que vous voulez - elle ne supprime pas le ".txt", elle le convertit en 4 espaces, et il fait également la même chose avec tout autre "t", "x" et "." dans le nom. Par exemple, "test1.txt" -> "es 1".