このコードの出力は2つのtxtファイルです。両方に対してforループを作成できますか?つまり、forループは2つ以上の出力を提供しますか? ID1とID2にはファイル名があります。 ID1とID2の各項目の最初の行を印刷し、それを出力1と出力2として保存したいが、2つのforループを使用したくない。私が探しているのは、タスクを実行するforループです。
#!/bin/bash
in=/a/b/c
li=/a/b/c/d/
g1=/a/s/t1/1.txt
g2=/a/s/t2/2.txt
for i in $(cat $li/ID1.txt); do
sed '1q;d' ${in}/${i}/${g1};
done > output1.txt
for i in $(cat $li/ID2.txt); do
sed '1q;d' ${in}/${i}/${g2};
done > output2.txt
答え1
さて、私は変数のパス名が何であるかを理解したようです。
for n in 1 2; do n=$n.txt
for f in $(cat "$li/ID$n")
do IFS= read -r l <"$in/$f/a/s/t${n%.*}/$n"
printf %s\\n "$l"
done > "output$n"; done
私考えるこれはあなたが追求することを達成します。もしそうなら、すべて、つまりcat
。
言い換えれば、ここで分割するときにcat
値を明確にし、拡張子でファイル名全体を解釈しないことが重要です。そのファイルの内容がわからないため、これ以上の提案はできません。$IFS
for ... in $(cmd sub)
$IFS
set -f
別のアプローチには、空の文字列区切り文字を含めることができます。断片化に大きく依存します$IFS
。拡張によって異なります。いいえ空の文字列をマーカーとして使用するため、空の文字列を含めます。これを変更せずに$IFS
デフォルト値に設定すると、拡張$(cat file)
に空の文字列は含まれません。次のように見えます。
io=/a/s/t1/1.txt
for f in $(cat "$li/ID1.txt") '' $(cat "$li/ID2.txt")
do [ -z "$f" ] && io=/a/s/t2/2.txt && continue
IFS= read -r l <"$in/$f/$io"
printf %s\\n "$l" >> "output${io##*/}"
done
それともそうすることができます...
n=0
for f in '' $(cat "$li/ID1.txt") '' $(cat "$li/ID2.txt")
do [ -z "$f" ] && exec >"output$((n+=1)).txt" && continue
IFS= read -r l <"$in/$f/a/s/t$n/$n.txt"
printf %s\\n "$l"
done
答え2
この特別なケースでは、ループはまったく必要ありません。
#!/usr/bin/env bash
in=/a/b/c
li=/a/b/c/d/
g1=/a/s/t1/1.txt
g2=/a/s/t2/2.txt
files1=$(sed "s#^#${in}/#;s#\$#/${g1}#" $li/ID1.txt | tr '\n' ' ')
files2=$(sed "s#^#${in}/#;s#\$#/${g2}#" $li/ID2.txt | tr '\n' ' ')
head -qn 1 $files1 > output1
head -qn 1 $files2 > output2
各行の先頭と末尾に追加files1=...
するために使用されます。これにより、ターゲットファイル名のリストが生成されます。その後、すべての項目を渡して最初の行を印刷できます。sed
$in
$g1
sed
重要:これはファイル名が正常であると仮定します(スペース、改行、またはその他の奇妙な文字を含まない)。そうでない場合は、お知らせください。空白のあるファイル名の場合、元のfor
反復方法も失敗します。
一般に、どの言語を使用しても繰り返しコードを記述する場合は、関数の使用を検討する必要があります。
#!/usr/bin/env bash
in=/a/b/c
li=/a/b/c/d/
g1=/a/s/t1/1.txt
g2=/a/s/t2/2.txt
firstline(){
_in="$1"
_g="$2"
file="$3"
while read i
do
sed '1q;d' ${in}/${i}/${g}
done < "$file"
}
firstline "$li/ID1.txt" "$in" "$g1" > output1.txt
firstline "$li/ID2.txt" "$in" "$g2" > output2.txt