のような文字列ファイル パスが与えられた場合、/foo/fizzbuzz.bar
bash を使用してそのfizzbuzz
文字列の一部だけを抽出するにはどうすればよいでしょうか。
14 に答える
Bash で # および % 演算子を使用してこれを行う方法を次に示します。
$ x="/foo/fizzbuzz.bar"
$ y=${x%.bar}
$ echo ${y##*/}
fizzbuzz
${x%.bar}
${x%.*}
ドットの後のすべてを削除するか${x%%.*}
、最初のドットの後のすべてを削除することもできます。
例:
$ x="/foo/fizzbuzz.bar.quux"
$ y=${x%.*}
$ echo $y
/foo/fizzbuzz.bar
$ y=${x%%.*}
$ echo $y
/foo/fizzbuzz
ドキュメントはBash のマニュアルにあります。末尾部分が一致するセクション${parameter%word}
を探します。${parameter%%word}
basename コマンドを見てください。
NAME="$(basename /foo/fizzbuzz.bar .bar)"
接尾辞 を削除するように指示し.bar
、結果はNAME=fizzbuzz
2 つの別々の操作で実行される純粋な bash:
パス文字列からパスを削除します。
path=/foo/bar/bim/baz/file.gif file=${path##*/} #$file is now 'file.gif'
パス文字列から拡張子を削除します。
base=${file%.*} #${base} is now 'file'.
basename を使用して、これを達成するために以下を使用しました。
for file in *; do
ext=${file##*.}
fname=`basename $file $ext`
# Do things with $fname
done;
これは、ファイル拡張子のアプリオリな知識を必要とせず、ファイル名に (拡張子の前に) ドットを含むファイル名がある場合でも機能します。ただし、プログラムが必要ですbasename
が、これは GNU coreutils の一部であるため、どのディストリビューションにも同梱されているはずです。
basename および dirname 関数は、あなたが求めているものです:
mystring=/foo/fizzbuzz.bar
echo basename: $(basename "${mystring}")
echo basename + remove .bar: $(basename "${mystring}" .bar)
echo dirname: $(dirname "${mystring}")
出力あり:
basename: fizzbuzz.bar
basename + remove .bar: fizzbuzz
dirname: /foo
純粋な bash の方法:
~$ x="/foo/bar/fizzbuzz.bar.quux.zoom";
~$ y=${x/\/*\//};
~$ echo ${y/.*/};
fizzbuzz
この機能は、man bash の「パラメーター拡張」で説明されています。awk、perl、sed など、非 bash の方法はたくさんあります。
編集: ファイルサフィックスのドットで動作し、サフィックス (拡張子) を知る必要はありませんが、名前自体のドットでは動作しません。
の使用basename
は、ファイル拡張子が何であるかを知っていることを前提としていますね。
そして、さまざまな正規表現の提案は、複数の「.」を含むファイル名に対応していないと思います。
以下はダブルドットに対応しているようです。ああ、「/」自体を含むファイル名(キック用)
Pascal の言葉を言い換えると、「このスクリプトは長くて申し訳ありません。短くする時間がありませんでした」
#!/usr/bin/perl
$fullname = $ARGV[0];
($path,$name) = $fullname =~ /^(.*[^\\]\/)*(.*)$/;
($basename,$extension) = $name =~ /^(.*)(\.[^.]*)$/;
print $basename . "\n";
他の投稿で提案されているように basename を使用できない場合は、いつでも sed を使用できます。これは(醜い)例です。これは最高ではありませんが、目的の文字列を抽出し、入力を目的の文字列に置き換えることで機能します。
echo '/foo/fizzbuzz.bar' | sed 's|.*\/\([^\.]*\)\(\..*\)$|\1|g'
出力が得られます
フィズバズ
perl -pe 's/\..*$//;s{^.*/}{}'
提案されたperlソリューションに注意してください。最初のドットの後のすべてを削除します。
$ echo some.file.with.dots | perl -pe 's/\..*$//;s{^.*/}{}'
some
あなたがperlでそれをしたいなら、これはうまくいきます:
$ echo some.file.with.dots | perl -pe 's/(.*)\..*$/$1/;s{^.*/}{}'
some.file.with
ただし、Bashを使用している場合は、y=${x%.*}
(またはbasename "$x" .ext
拡張機能を知っている場合)を使用したソリューションの方がはるかに簡単です。
ベース名はそれを行い、パスを削除します。サフィックスが指定されていて、ファイルのサフィックスと一致する場合はサフィックスも削除されますが、コマンドに指定するサフィックスを知る必要があります。それ以外の場合は、 mv を使用して、別の方法で新しい名前を特定できます。