尝试合并我拥有的一些数据。输入看起来像这样:
foo bar
foo baz boo
abc def
abc ghi
我希望输出看起来像:
foo bar baz boo
abc def ghi
我有一些想法在shell脚本中使用一些数组,但我一直在寻找更优雅或更快的解决方案。
答案 0 :(得分:3)
加入怎么样?
file="file"
join -a1 -a2 <(sort "$file" | sed -n 1~2p) <(sort "$file" | sed -n 2~2p)
那里的seds只是在奇数行和偶数行上分割文件
答案 1 :(得分:2)
虽然pixelbeat的答案有效,但我不能说我非常热衷于它。我想我会用awk这样的东西:
{ for (i=2; i<=NF; i++) { lines[$1] = lines[$1] " " $i;} }
END { for (i in lines) printf("%s%s\n", i, lines[i]); }
这不应该要求对数据进行预排序,并且无论字段的数量或长度如何都应该正常工作(当然,没有内存溢出)。它唯一明显的缺点是它的输出是任意顺序的。如果你需要它排序,你需要通过排序管道输出(但回到原始顺序将是其他的东西)。
答案 2 :(得分:2)
awk解决方案
awk '
{key=$1; $1=""; x[key] = x[key] $0}
END {for (key in x) {print key x[key]}}
' filename
答案 3 :(得分:0)
如果第一个字段的长度是固定的,则可以将uniq
与-w
选项一起使用。否则你晚上想要使用awk(警告:未经测试的代码):
awk '
BEGIN{last='';}
{
if ($1==last) {
for (i = 1; i < NF;i++) print $i;
} else {
print "\n", $0;
last = $1;
}
}'
答案 4 :(得分:0)
Pure Bash,用于真正的交替线:
infile="paste.dat"
toggle=0
while read -a line ; do
if [ $toggle -eq 0 ] ; then
echo -n "${line[@]}"
else
unset line[0] # remove first element
echo " ${line[@]}"
fi
((toggle=1-toggle))
done < "$infile"
答案 5 :(得分:0)
基于fgm的纯Bash snippet:
text='
foo bar
foo baz boo
abc def
abc ghi
'
count=0
oneline=""
firstword=""
while IFS=" " read -a line ; do
let count++
if [[ $count -eq 1 ]]; then
firstword="${line[0]}"
oneline="${line[@]}"
else
if [[ "$firstword" == "${line[0]}" ]]; then
unset line[0] # remove first word of line
oneline="${oneline} ${line[@]}"
else
printf "%s\n" "${oneline}"
oneline="${line[@]}"
firstword="${line[0]}"
fi
fi
done <<< "$text"