${ls ...}をbashに置き換えるときにエラーが発生しました。

${ls ...}をbashに置き換えるときにエラーが発生しました。

次のエラーが発生します。

./assemblyDB.116.las
test.sh: line 9: ${ls $filename | sed 's/assemblyDB.//' | sed 's/.las//'}: bad substitution

スクリプトは次のとおりです。

for filename in $(find . -type f -name "assemblyDB.*.las"); do
   echo $filename
   no=${ls $filename | sed 's/assemblyDB.//' | sed 's/.las//'}
   echo $no
done

答え1

${ ... }(中括弧) 複数表示パラメータ拡張、最も簡単な方法は変数の値を拡張することです。コードの中かっこ内の内容は、有効なパラメータ名やその他の拡張ではないため、シェルは文句を言います。

構文が$( ... )(一般括弧)であるコマンドの置換を望むようです。

また、少し不要なようです。変数はファイル名に展開され、渡さlsれます。ただ代わりに使うこともできます。ls $filename | sed...lsecho "$filename" | sed ...

つまり、シェルから直接次のように変更できます。

no="${filename/assemblyDB.}"   # remove first match
no="${no/.las}"

または標準演算子を使用してください。

no="${filename#assemblyDB.}"   # remove from start of string
no="${no%.las}"                # remove from end of string

これを実行すると、正規表現のすべての文字を一致させるようにsed注意することができるため、バックスラッシュで引用する方がより正確になります。インスタンスに2つのコマンドを提供する.こともできます。sedsed -e 's/assemblyDB\.//' -e 's/\.las//'

それではfor filename in $(find . -type f -name "assemblyDB.*.las"); do問題があります。lsを解析する主にファイル名のスペースとワイルドカードが原因で問題が発生します。 ksh/Bash/zsh では、シェルでフルループを実行できます。

shopt -s globstar         # in Bash
for filename in **/assemblyDB.*.las; do
    ...

答え2

コマンド置換(3行)

for filename in $(find . -type f -name "assemblyDB.*.las"); do
   echo $filename
   no=$(ls $filename | sed 's/assemblyDB.//' | sed 's/.las//')
   echo $no
done

lsすでに指摘したように、これは(3行目、いいえ)と同じです。

for filename in $(find . -type f -name "assemblyDB.*.las"); do
   echo $filename
   no=$(echo $filename | sed 's/assemblyDB.//' | sed 's/.las//')
   echo $no
done

またはより短い(ライン4が消え、今すぐエコーされています)

for filename in $(find . -type f -name "assemblyDB.*.las"); do
   echo $filename
   echo $filename | sed 's/assemblyDB.//' | sed 's/.las//'
done

sedコマンドは次のように単純化できます(ライン3)。

for filename in $(find . -type f -name "assemblyDB.*.las"); do
   echo $filename
   echo $filename | sed 's/assemblyDB.//;s/.las//'
done

または sed を使用して中間部分を抽出します。 (まだ3行目)

for filename in $(find . -type f -name "assemblyDB.*.las"); do
   echo $filename
   echo $filename | sed -r 's/.*assemblyDB.(.*).las/\1/'" 
done

今、for-iteratorの代わりにfind-iterator:(ライン1〜3と4が消えました)

find . -type f -name "assemblyDB.*.las" -printf "%f\n" -exec sh -c "
   echo {} | sed -r 's/.*assemblyDB.(.*).las/\1/'"  ";"

assemblyDB.11.las
11
assemblyDB.9.las
9
assemblyDB.10.las
10

ファイル名がこの順序または類似の順序になっている場合は、以下も機能します。

for i in {8..12} ; do ls assemblyDB.$i.las && echo $i ; done 2>/dev/null

assemblyDB.9.las
9
assemblyDB.10.las
10
assemblyDB.11.las
11

(8と12は、シーケンスに欠落しているファイルを示すために含まれています)。

答え3

${}バックティックを使用する代わりに、`[キーボードのEscape]の下にあるボタンを押します。 ]

関連情報