10個のテキストファイルがあり、各ファイルとそのペアをpaste
したいので、合計5個のファイルがあります。
私は以下を試しました:
for i in 4_1 5_1 6_1 7_1 8_1
do
for j in 4_2 5_2 6_2 7_2 8_2
do
paste ${i}.txt ${j}.txt > ${i}.${j}.txt
done
done
ただし、このコードは、一致するペアを組み合わせるだけでなく、可能なすべての組み合わせを組み合わせます。
だから私はファイル4_1.txt
と組み合わせて4_2.txt
、5_1.txt
と5_2.txt
など.
1つの変数を使用して実行し、そのアクションを実行する場合は、1つのループを使用するだけです。
for file in 4 5 6 7 8
do
paste "${file}_1" "${file}_2"
done
これはします
paste 4_1 4_2
paste 5_1 5_2
...
現在質問されている質問に関して、フェドルキが現在提案している回答に同意します。以下は、より一般的な答えを提供するためにのみ提供されています。
(bash 4.0以降の)より一般的なアプローチの1つは、ペアを連想配列に格納することです。
declare -A pairs=( [4_1]=4_2 [5_1]=5_2 [6_1]=6_2 [7_1]=7_2 [8_1]=8_2 )
for i in "${!pairs[@]}"; do
j=${pairs[$i]}
paste "$i.txt" "$j.txt" >"${i}.${j}.txt"
done
もう1つ(以前のリリースのbashと互換性があります)は、複数の従来の配列を使用することです。
is=( 4_1 5_1 6_1 7_1 8_1 )
js=( 4_2 5_2 6_2 7_2 8_2 )
for idx in "${!is[@]}"; do
i=${is[$idx]}
j=${js[$idx]}
paste "$i.txt" "$j.txt" >"$i.$j.txt"
done
連想配列を使用できます。
animals=(dog cat mouse)
declare -A size=(
[dog]=big
[cat]=medium
[mouse]=small
)
declare -A sound=(
[dog]=barks
[cat]=purrs
[mouse]=cheeps
)
for animal in "${animals[@]}"; do
echo "$animal is ${size[$animal]} and it ${sound[$animal]}"
done
これにより、ペア、トリプルなどをトラバースできます。
ファイルのペアが存在する一般的なパターンがあり、ペアの名前の1つは他の名前から簡単に派生できます。名前がわかっているファイルがXで、他のファイルがYの場合、次の一般的な使用例があります。
これらはすべて、同じ大まかなコードスケルトンに適しています。
for x in path/to/base*.ext; do
dir=${x%/*} # Trim trailing file name, keep dir
base=${x##*/} # Trim any leading directory
# In this case, $y has a different subdirectory and a different extension
y=${dir%/to}/from/${base%.ext}.newext
# Maybe check if y exists? Or doesn't exist?
if [ -e "$y" ]; then
echo "$0: $y already exists -- skipping" >&2
continue
fi
mv or ffmpeg or awk or whatever "$x" and "$y"
done
ここで重要なのは、y
がx
からいくつかの単純な変数置換で導出できるという観察です。したがって、x
値をループして、ループ内の対応するy
値を見つけます。
ここでは、シェルの組み込み${variable#prefix}
演算子と${variable%suffix}
演算子を使用して、変数の値を返し、先頭のprefix
または末尾のsuffix
をそれぞれ切り捨てています。 (最短ではなく、最長の一致ではなく##
と%%
もあります。#
または%
の後の式は、通常のシェルglobパターンです。)これらは通常必要なものすべてですが、この簡単なジョブ(実際には通常、外部プロセスを回避する必要がある場合)でも、sed
またはawk
スクリプトが頻繁に表示されます。より厳しい転換のために。
異なるディレクトリに散在するx
ファイルをループする必要がある場合、おそらくループは次のようなもので始まるはずです
find dir1 dir2 etc/and/so/forth -type f -name 'x-files*.ext' -print |
while IFS='' read -r x; do
:
同様の質問でよく見られる問題は、$x
および$y
を正しく引用できない回答です。一般に、ファイル名を含む変数は常に二重引用符で囲む必要があります。
XとYが無関係の場合、一般的な解決策は、マッピングを含むヒアドキュメントをループすることです。
while read -r x y; do
: stuff with "$x" and "$y"
done <<'____HERE'
first_x_value first_y_value
another_x corresponding_y
random surprise
____HERE
上記は私にとってはうまくいきませんでしたが、次は順序付きリストからペアで値を読み取ります
(余分な 'read-lines'を追加するペア以上になる場合があります:-)
while read x; do
read y
echo $x $y
done << '___HERE'
X1
Y1
X2
Y2
X3
Y3
___HERE
作り出す
X1 Y1
X2 Y2
X3 Y3
read -r x y
とread x && read y
の使用には違いがあります
while read -r x y; do
echo "$x and $y"
done <<'____HERE'
A B
C D
____HERE
印刷します
A and B
C and D
一方、
while read x && read y; do
echo "$x and $y"
done <<'____HERE'
A B
C D
____HERE
印刷します
A B and C D
最初の例はspace
で分割し、2番目の例はnewline
で分割します。