web-dev-qa-db-ja.com

bashを使用してパス文字列の1つの要素を取得します

次を実行して読み取るファイルパスを含むASCIIファイルがあります。

while read p; do echo $p; done < filelist.txt

ファイルには、次のパターンのファイルパスが含まれています。

./first/example1/path
./second/example1/path
./third/example2/path

パス文字列の特定の部分(/から/)を取得するにはどうすればよいですか。私は印刷する出力を取得する必要があります:

first
second
third

そしてまた

example1
example1
example2

正規表現とsedを使用してこれを実行する方法があると確信していますが、私はそれに慣れていません。

8
mcExchange

cutを使用します。

$ cat filelist.txt
./first/example1/path
./second/example1/path
./third/example2/path

$ cut -d/ -f2 filelist.txt 
first
second
third

$ cut -d/ -f3 filelist.txt 
example1
example1
example2

-d/は列の区切り文字を/に設定し、-f2は2番目の列を選択します。

もちろん、ファイル名の代わりにBash変数を使用したり、cutコマンドにデータをパイプしたりすることもできます。

cut -d/ -f3 $MyVariable
echo ./another/example/path | cut -d/ -f3
14
Byte Commander

read変数を使用して、IFSコマンドで直接実行できます。

$ while IFS=/ read -r p1 p2 p3 r; do echo "$p2"; done < filelist.txt 
first
second
third
10
steeldriver

awkを使用できます

pilot6@Pilot6:~$ cat filelist.txt
./first/example1/path
./second/example1/path
./third/example2/path

pilot6@Pilot6:~$ awk -F "/" '{print $2}' filelist.txt
first
second
third

pilot6@Pilot6:~$ awk -F "/" '{print $3}' filelist.txt
example1
example1
example2
5
Pilot6

パスの要素が必要な場合は、 awkcut など、文字列をフィールドに分割できるものを使用するのが最善です python 、または Perl 。ただし、 bash は、パターン置換を使用してすべてを配列にスローするパラメーター置換を使用してジョブを実行することもできます。

$> echo ${FILE//\//\ }                                                         
sys class backlight intel_backlight brightness
$> ARRAY=( ${FILE//\//" " } )                                                  
$> echo ${ARRAY[2]}
backlight

$> FILE="./dir1/dir2/file.txt"                                                 
$> ARRAY=( ${FILE//\/" "} )
$> echo ${ARRAY[@]}                                                            
. dir1 dir2 file.txt
$> echo ${ARRAY[1]}
dir1

これで、パスから作成されたアイテムの配列ができました。パスにスペースが含まれている場合、内部フィールド区切り文字IFSの変更が必要になる場合があることに注意してください。

2

Bashとcutを使用する方法がありますが、Perlを使用する代替方法もあります。

Perl -F/ -lane 'print(@F[1])' filelist.txt

2番目の/で区切られたフィールドと

Perl -F/ -lane 'print(@F[2])' filelist.txt

3番目の/で区切られたフィールド。

  • -l:自動行末処理を有効にします。 2つの別々の効果があります。まず、-nまたは-pと共に使用すると、自動的に$ /(入力レコードの区切り記号)が削除されます。次に、$ \(出力レコードセパレーター)にoctnumの値を割り当てて、printステートメントがそのセパレーターを再び追加するようにします。 octnumが省略された場合、$ \を現在の値$ /に設定します。
  • -a:-nまたは-pとともに使用すると、自動分割モードがオンになります。 @F配列への暗黙的なsplitコマンドは、-nまたは-pによって生成される暗黙的なwhileループ内で最初に実行されます。
  • -n:は、Perlがプログラムの周りに次のループを想定し、sed -nまたはawkのようなファイル名の引数を反復処理します。

    LINE:
      while (<>) {
          ...             # your program goes here
      }
    
  • -e:プログラムの1行を入力するために使用できます。

  • print(@F[N]):N番目のフィールドを出力します。
% cat filelist.txt 
./first/example1/path
./second/example1/path
./third/example2/path
% Perl -F/ -lane 'print(@F[1])' filelist.txt
first
second
third
% Perl -F/ -lane 'print(@F[2])' filelist.txt
example1
example1
example2
1
kos