467

のような文字列ファイル パスが与えられた場合、/foo/fizzbuzz.barbash を使用してそのfizzbuzz文字列の一部だけを抽出するにはどうすればよいでしょうか。

4

14 に答える 14

671

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}

于 2008-09-24T03:54:28.167 に答える
274

basename コマンドを見てください。

NAME="$(basename /foo/fizzbuzz.bar .bar)"

接尾辞 を削除するように指示し.bar、結果はNAME=fizzbuzz

于 2008-09-24T03:38:03.663 に答える
57

2 つの別々の操作で実行される純粋な bash:

  1. パス文字列からパスを削除します。

    path=/foo/bar/bim/baz/file.gif
    
    file=${path##*/}  
    #$file is now 'file.gif'
    
  2. パス文字列から拡張子を削除します。

    base=${file%.*}
    #${base} is now 'file'.
    
于 2014-05-06T14:20:03.097 に答える
21

basename を使用して、これを達成するために以下を使用しました。

for file in *; do
    ext=${file##*.}
    fname=`basename $file $ext`

    # Do things with $fname
done;

これは、ファイル拡張子のアプリオリな知識を必要とせず、ファイル名に (拡張子の前に) ドットを含むファイル名がある場合でも機能します。ただし、プログラムが必要ですbasenameが、これは GNU coreutils の一部であるため、どのディストリビューションにも同梱されているはずです。

于 2014-04-11T17:07:04.220 に答える
17

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
于 2008-09-24T03:40:06.123 に答える
14

純粋な bash の方法:

~$ x="/foo/bar/fizzbuzz.bar.quux.zoom"; 
~$ y=${x/\/*\//}; 
~$ echo ${y/.*/}; 
fizzbuzz

この機能は、man bash の「パラメーター拡張」で説明されています。awk、perl、sed など、非 bash の方法はたくさんあります。

編集: ファイルサフィックスのドットで動作し、サフィックス (拡張子) を知る必要はありませんが、名前自体のドットでは動作しません。

于 2008-09-24T03:39:05.130 に答える
7

の使用basenameは、ファイル拡張子が何であるかを知っていることを前提としていますね。

そして、さまざまな正規表現の提案は、複数の「.」を含むファイル名に対応していないと思います。

以下はダブルドットに対応しているようです。ああ、「/」自体を含むファイル名(キック用)

Pascal の言葉を言い換えると、「このスクリプトは長くて申し訳ありません。短くする時間がありませんでした」


  #!/usr/bin/perl
  $fullname = $ARGV[0];
  ($path,$name) = $fullname =~ /^(.*[^\\]\/)*(.*)$/;
  ($basename,$extension) = $name =~ /^(.*)(\.[^.]*)$/;
  print $basename . "\n";
 
于 2008-09-24T05:07:37.880 に答える
3

他の投稿で提案されているように basename を使用できない場合は、いつでも sed を使用できます。これは(醜い)例です。これは最高ではありませんが、目的の文字列を抽出し、入力を目的の文字列に置き換えることで機能します。

echo '/foo/fizzbuzz.bar' | sed 's|.*\/\([^\.]*\)\(\..*\)$|\1|g'

出力が得られます

フィズバズ

于 2008-09-24T11:12:06.803 に答える
3
perl -pe 's/\..*$//;s{^.*/}{}'
于 2008-09-24T03:39:34.317 に答える
2

提案された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拡張機能を知っている場合)を使用したソリューションの方がはるかに簡単です。

于 2010-06-19T10:35:04.550 に答える
1

ベース名はそれを行い、パスを削除します。サフィックスが指定されていて、ファイルのサフィックスと一致する場合はサフィックスも削除されますが、コマンドに指定するサフィックスを知る必要があります。それ以外の場合は、 mv を使用して、別の方法で新しい名前を特定できます。

于 2008-11-15T00:47:41.193 に答える