ほとんどの場合、次のような入力ファイルを取得します。
java-1.8.0-openjdk.x86_64 1:1.8.0.232.b09-1.el6_10 asyum:ol6_latest
java-1.8.0-openjdk-headless.x86_64 1:1.8.0.232.b09-1.el6_10 asyum:ol6_latest
kernel.x86_64 2.6.32-754.23.1.el6 asyum:ol6_latest
...whileループがあり、次のコードを使用して各行に対してfield1とfield2を正常にキャプチャできます。
f1=$(echo $line | awk '{print $1}')
f2=$(echo $line | awk '{print $2}')
ただし、時々、次のような入力ファイルが表示されます。
java-1.8.0-openjdk.x86_64 1:1.8.0.232.b09-1.el6_10 asyum:ol6_latest
java-1.8.0-openjdk-headless.x86_64
1:1.8.0.232.b09-1.el6_10 asyum:ol6_latest
kernel.x86_64 2.6.32-754.23.1.el6 asyum:ol6_latest
(ライン2を区切る追加の改行があることに注意してください。)
このタイプの入力をプログラムで処理するためのヒント/コツがあります(入力ファイルを手動でクリーンアップする代わりに)。
答え1
以下は、先行スペースにのみ依存するソリューションです。予想されるフィールド数に依存しません。
これGNUマニュアルsed
「空白で始まる行を連結する」方法を提供します。
sed -E ':a ; $!N ; s/\n\s+/ / ; ta ; P ; D'
マニュアルでは、移植可能な(GNUではない)バリアントは次のように主張しています。
sed -e :a -e '$!N;s/\n */ /;ta' -e 'P;D'
答え2
これにより、目的の効果を得ることができます。
#!/usr/bin/env bash
while read line; do
declare -a array=($line)
if test ${#array[@]} != 3; then
read line2
array+=($line2)
fi
f1=${array[0]}
f2=${array[1]}
echo $f1 $f2
done
run with : test.sh < inputfile
行に3つの項目が含まれていることを確認し、そうでない場合は次の行を結合します。
答え3
とにかくそれを使っているので、awk
完全に依存するのはどうですか?努力する
read f1 f2 <<< $(awk '{while (NF < 3) {getline X; $0 = $0 FS X}; print $1, $2}' file)
答え4
入力データの正しい形式の各行が3つの単語(ここでは空白文字を含まない文字列で緩く定義されている)で構成されていると仮定すると、入力データを前処理できます。
<input_file tr -s '[:blank:]' '\n' | paste - - - | column -t
<newline>
ここでは、すべての空白文字(文字を含む)を単一に置き換え<newline>
、結果を3単語行に再配置し、出力形式をきれいに指定します。最後のステップは、あなたの質問を考慮する際に不要な装飾的なステップです。