大多数时候,我得到的输入文件如下所示:
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
既然你awk
无论如何都在使用它,为什么不完全依赖它呢?尝试
read f1 f2 <<< $(awk '{while (NF < 3) {getline X; $0 = $0 FS X}; print $1, $2}' file)
答案4
假设输入数据的每个格式正确的行都由三个单词组成(此处宽松地定义为不包含任何空白字符的字符串),您可以预处理输入数据:
<input_file tr -s '[:blank:]' '\n' | paste - - - | column -t
<newline>
在这里,我们用单个替换任何空白字符(包括字符) <newline>
,将结果重新排列为三个单词的行,并很好地格式化输出 - 考虑到您的问题,最后一个是不必要的装饰步骤。