Gegeven een string-bestandspad zoals /foo/fizzbuzz.bar
, hoe zou ik bash gebruiken om alleen de fizzbuzz
gedeelte van genoemde tekenreeks te extraheren?
Antwoord 1, Autoriteit 100%
Hier is hoe het te doen met de # en% operators in bash.
$ x="/foo/fizzbuzz.bar"
$ y=${x%.bar}
$ echo ${y##*/}
fizzbuzz
${x%.bar}
kan ook ${x%.*}
om alles te verwijderen na een punt of ${x%%.*}
om alles na de eerste punt te verwijderen.
Voorbeeld:
$ x="/foo/fizzbuzz.bar.quux"
$ y=${x%.*}
$ echo $y
/foo/fizzbuzz.bar
$ y=${x%%.*}
$ echo $y
/foo/fizzbuzz
Documentatie is te vinden in de BASH-handleiding . Zoek naar ${parameter%word}
en ${parameter%%word}
trailing portie matching sectie.
Antwoord 2, Autoriteit 40%
Kijk naar het Basename-opdracht:
NAME="$(basename /foo/fizzbuzz.bar .bar)"
instrueert het om het achtervoegsel te verwijderen .bar
, resulteert in NAME=fizzbuzz
Antwoord 3, Autoriteit 8%
Pure bash, gedaan in twee afzonderlijke operaties:
-
Verwijder het pad van een pad-string:
path=/foo/bar/bim/baz/file.gif file=${path##*/} #$file is now 'file.gif'
-
Verwijder de extensie van een pad-string:
base=${file%.*} #${base} is now 'file'.
Antwoord 4, Autoriteit 3%
Basename gebruiken Ik heb het volgende gebruikt om dit te bereiken:
for file in *; do
ext=${file##*.}
fname=`basename $file $ext`
# Do things with $fname
done;
Dit vereist geen priori-kennis van de bestandsextensie en werkt, zelfs als u een bestandsnaam hebt die stippen in zijn bestandsnaam (voor zijn extensie) heeft; Het vereist het programma basename
Hoewel, maar dit maakt deel uit van de GNU COREUTILS, zodat het met elke distro moet worden verzonden.
Antwoord 5, Autoriteit 2%
De Basename en Dirname-functies zijn wat u zoekt:
mystring=/foo/fizzbuzz.bar
echo basename: $(basename "${mystring}")
echo basename + remove .bar: $(basename "${mystring}" .bar)
echo dirname: $(dirname "${mystring}")
heeft de uitvoer:
basename: fizzbuzz.bar
basename + remove .bar: fizzbuzz
dirname: /foo
Antwoord 6, Autoriteit 2%
Pure bash-manier:
~$ x="/foo/bar/fizzbuzz.bar.quux.zoom";
~$ y=${x/\/*\//};
~$ echo ${y/.*/};
fizzbuzz
Deze functionaliteit wordt uitgelegd op man bash onder “parameter expansion”. Non Bash-manieren in overvloed: Awk, Perl, SED enzovoort.
EDIT: werkt met stippen in bestand achtervoegsels en hoeft het achtervoegsel (extensie) niet te kennen, maar werkt niet werk met stippen in de naam zelf.
Antwoord 7
Gebruik basename
Aangenomen dat u weet wat de bestandsextensie is, nietwaar?
En ik geloof dat de verschillende suggesties voor reguliere expressies niet opgewassen zijn tegen een bestandsnaam met meer dan één “.”
Het volgende lijkt te gaan met dubbele punten. Oh, en bestandsnamen die zelf een “/” bevatten (alleen voor de kick)
Om Pascal te parafraseren: “Sorry, dit script is zo lang. Ik had geen tijd om het korter te maken”
#!/usr/bin/perl
$fullname = $ARGV[0];
($path,$name) = $fullname =~ /^(.*[^\\]\/)*(.*)$/;
($basename,$extension) = $name =~ /^(.*)(\.[^.]*)$/;
print $basename . "\n";
Antwoord 8
In aanvulling op de POSIX-conforme syntaxisgebruikt in dit antwoord,
basename string [suffix]
zoals in
basename /foo/fizzbuzz.bar .bar
GNU basename
ondersteunt een andere syntaxis:
basename -s .bar /foo/fizzbuzz.bar
met hetzelfde resultaat. Het verschil en voordeel is dat -s
-a
impliceert, wat meerdere argumenten ondersteunt:
$ basename -s .bar /foo/fizzbuzz.bar /baz/foobar.bar
fizzbuzz
foobar
Dit kan zelfs bestandsnaam veilig worden gemaakt door de uitvoer te scheiden met NUL BYTES met behulp van de optie -z
, bijvoorbeeld voor deze bestanden met blanco, newlines en globetekens (geciteerd door ls
):
$ ls has*
'has'$'\n''newline.bar' 'has space.bar' 'has*.bar'
lezen in een array:
$ readarray -d $'\0' arr < <(basename -zs .bar has*)
$ declare -p arr
declare -a arr=([0]=$'has\nnewline' [1]="has space" [2]="has*")
readarray -d
vereist bash 4.4 of nieuwer. Voor oudere versies moeten we lus:
while IFS= read -r -d '' fname; do arr+=("$fname"); done < <(basename -zs .bar has*)
Antwoord 9
perl -pe 's/\..*$//;s{^.*/}{}'
Antwoord 10
Als u basenaam niet kunt gebruiken zoals gesuggereerd in andere berichten, kunt u altijd SED gebruiken. Hier is een (lelijk) voorbeeld. Het is niet de beste, maar het werkt door de gewenste string te extraheren en de invoer te vervangen door de gewenste string.
echo '/foo/fizzbuzz.bar' | sed 's|.*\/\([^\.]*\)\(\..*\)$|\1|g'
Hiermee krijgt u de uitvoer
Fizzbuzz
Antwoord 11
Pas op voor de voorgestelde PERL-oplossing: het verwijdert alles na de eerste punt.
$ echo some.file.with.dots | perl -pe 's/\..*$//;s{^.*/}{}'
some
Als u het met PERL wilt doen, werkt dit:
$ echo some.file.with.dots | perl -pe 's/(.*)\..*$/$1/;s{^.*/}{}'
some.file.with
Maar als je Bash gebruikt, de oplossingen met y=${x%.*}
(of basename "$x" .ext
als je de extensie kent ) zijn veel eenvoudiger.
Antwoord 12
Het best beoordeelde antwoord combineren met het op één na best beoordeelde antwoord om de bestandsnaam te krijgen zonder het volledige pad:
$ x="/foo/fizzbuzz.bar.quux"
$ y=(`basename ${x%%.*}`)
$ echo $y
fizzbuzz
Antwoord 13
De basisnaam doet dat, verwijdert het pad. Het zal ook het achtervoegsel verwijderen als het wordt gegeven en als het overeenkomt met het achtervoegsel van het bestand, maar u moet het achtervoegsel weten om aan de opdracht te geven. Anders kun je mv gebruiken en op een andere manier uitzoeken wat de nieuwe naam zou moeten zijn.
Antwoord 14
U kunt gebruiken
mv *<PATTERN>.jar "$(basename *<PATTERN>.jar <PATTERN>.jar).jar"
Bijvoorbeeld: – Ik wilde -SNAPSHOT
uit mijn bestandsnaam verwijderen. Voor dat gebruikte onderstaande commando
mv *-SNAPSHOT.jar "$(basename *-SNAPSHOT.jar -SNAPSHOT.jar).jar"