次のgrepコマンドを実行すると、期待した結果が表示されます。
$ grep -o -E '/ |:|\\|<|>|\*|\?|\"| $' <<< '/home/ttwaro/temp/Test/This is a Test: Testing Number 1?/This is Test: Testing Number 1?.eng.srt'
:
?
:
?
しかし、出力を配列に入れようとすると疑問符 "?"代わりに文字「C」が表示されます。私は何が間違っていましたか?
$ array=()
$ array+=($(grep -o -E '/ |:|\\|<|>|\*|\?|\"| $' <<< '/home/ttwaro/temp/Test/This is a Test: Testing Number 1?/This is Test: Testing Number 1?.eng.srt'))
$ printf '%s\n' "${array[@]}"
:
C
:
C
答え1
これが発生する理由は、C
コマンドを実行するディレクトリに指定されたファイルまたはサブディレクトリがあり、?
それに合わせてglobが拡張されるためです。より簡単な例を挙げると、次のようになります。
$ ls -la
total 92
drwxr-xr-x 2 terdon terdon 16384 Mar 26 18:53 .
drwxr-xr-x 170 terdon terdon 73728 Mar 26 13:57 ..
$ array=( $( printf '?\n' ) )
$ printf '%s\n' "${array[@]}"
?
次に、次のファイルを作成してC
再試行します。
$ touch C
$ array=( $( printf '?\n' ) )
$ printf '%s\n' "${array[@]}"
C
作業順序によって異なります。を実行すると、array=( $( printf '?\n' ) )
次のことが順番に発生します。
- 実行され
printf '?\n'
、を返します?
。 - これ引用しない
?
シェルによって一致するファイル名に展開されます。この場合はC
。 - 拡張グローブは配列の要素
C
として保存されます。0
array
これを防ぐには、ワイルドカードがシェルから保護されるように配列割り当てを引用する必要があります。
$ array=( "$( printf '?\n' )" )
$ printf '%s\n' "${array[@]}"
?
または、元の例を使用して、次の手順を実行します。
$ array=( "$(grep -o -E '/ |:|\\|<|>|\*|\?|\"| $' <<< '/home/ttwaro/temp/Test/This is a Test: Testing Number 1?/This is Test: Testing Number 1?.eng.srt')" )
$ printf '%s\n' "${array[@]}"
:
?
:
?
ただし、引用されているため、結果全体が単一の文字列として表示されるため、配列には1つの要素しか含まれません。
$ for ((i=0;i<${#array[@]}; i++)); do
printf 'element %s is %s\n' "$i" "${array[i]}";
done
element 0 is :
?
:
?
各結果を配列の別々の要素として取得するには、以下の提案に従って次のことを行う必要があります。ゴードン・デイビソンコメントから:
$ readarray -t array < <(grep -o -E '/ |:|\\|<|>|\*|\?|\"| $' <<< '/home/ttwaro/temp/Test/This is a Test: Testing Number 1?/This is Test: Testing Number 1?.eng.srt')
$ for ((i=0;i<${#array[@]}; i++)); do
printf 'element %s is %s\n' "$i" "${array[i]}";
done
element 0 is :
element 1 is ?
element 2 is :
element 3 is ?
grep
これにより、シェルは出力を表示できないため、引用する必要はありません。
最後に、結果に2つのsがある理由は、C
配列に保存されると各sがaに拡張されるためです?
。C
$ array=( ? ? ? )
$ printf '%s\n' "${array[@]}"
C
C
C