制御ファイルから番号を読み取り、データファイルから一致する行番号を抽出します。

制御ファイルから番号を読み取り、データファイルから一致する行番号を抽出します。

制御ファイル cntl.txt があります

2
3
5

データファイル - data.txt

red
blue
yellow
green
violet
orange

制御ファイルから一致する行を読み取る必要があります。ここで期待される出力は次のようになります。

blue
yellow 
violet

答え1

非常に非効率的な解決策の例:

for i in $(<control.txt); do awk -v c=$i 'NR~c{ print $0 }' data.txt; done;

今夜私が学んだ良い解決策も報告します:

awk 'FNR==NR{ z[$0]++;next }; FNR in z' control.txt data.txt

答え2

のみ使用POSIX指定Sedの特徴:

sed -n -e "$(sed '/./s/$/p/' cntl.txt)" data.txt

もちろん、cntl.txtファイルに数字以外の行がある場合は、エラーが発生する可能性があります。ただし、空行がある場合は、正しく処理されます (つまり、出力に影響しません)。

答え3

これを試して:

join <(nl data.txt|sort -k1b,1) <(cat cntl.txt|sort -k1b,1) | sort -nk1,1 | cut -d' ' -f2-

nl - 行を列挙します

 1  red
 2  blue
 3  yellow
 4  green
 5  violet
 6  orange

| sort -k1b,1 - 行番号(最初のフィールド)で辞書順に並べ替えます

cat cntl.txt| sort -k1b,1 - 制御ファイルを同じ順序でソートします

2
3
5

join <() <() - ソートされた(番号付けされた)「データ」とソートされた「コントロール」を最初のフィールド(つまり行番号)で結合します。

2 blue
3 yellow
5 violet

|sort -nk1,1 - 結果を数値順に再ソートします(行を元の順序に戻します)

| cut -d' ' -f2- - 行番号フィールドを削除します

blue
yellow
violet

答え4

別の解決策としては、

IFS=$'\n' read -d '' -r -a colors < 'data.txt'; unset IFS;

for i in $(<cntl.txt); do
        echo ${colors[i-1]} 
done

IFS 行は、内部ファイル区切りを改行として設定し、data.txt の各行を配列に挿入します。その後、cntl.txt 内の行をループし、そこから指定されたインデックスの配列要素を出力します (data.txt は 0 ではなく 1 から始まるため、マイナス 1 になります。そうでなければ不要です)。

関連情報