单列数据到多列

时间:2013-03-16 18:17:48

标签: linux bash shell sed awk

我在单个列中有正浮点值或负浮点值的数据,由两个空行分隔。

1.0
-2.0


3.0
4.0


-5.0
6.0


-7.0
8.0

在bash中,将这些数据放入多个列的最佳方法是什么,以便最终结果如下所示:

1.0 3.0 -5.0 -7.0
-2.0 4.0 6.0 8.0

在理想情况下,解决方案不仅适用于数字,还适用于以类似方式分隔的文本。

6 个答案:

答案 0 :(得分:11)

怎么样:

$ grep -v '^\s*$' file | pr -ts" " --columns 4 
1.0 3.0 -5.0 -7.0
-2.0 4.0 6.0 8.0

grep用于删除空行,pr用于格式化输出。

答案 1 :(得分:2)

这可能适合你(GNU sed):

sed -r '/./!d;$!N;2{h;d};G;s/^(.*)\n(.*)\n(.*)\n(.*)$/\3 \1\n\4 \2/;$!{h;d}' file
  • /./!d如果该行不包含字符,则将其删除。
  • $!N如果该行不是最后一行,则添加换行符,并将以下行附加到模式空间(PS)。
  • 第二行
  • 2{h;d},将PS复制到保留空间(HS),然后将其删除。
  • 所有其他行的
  • G将HS附加到PS。
  • s/^(.*)\n(.*)\n(.*)\n(.*)$/\3 \1\n\4 \2/将PS重新排列为所需的顺序。
  • $!{h;d}除了最后将PS复制到HS之外的所有行,然后删除PS。 这意味着在遇到最后一行时,PS的内容将被打印出来。

答案 2 :(得分:1)

这是一个更长但更易读的解决方案:

a=() b=() i=0
while read line ; do
    case $i in
        0) a+=($line) ;;
        1) b+=($line) ;;
    esac
    ((i++))
    if ((i == 4)); then i=0; fi
done < data.txt

echo ${a[*]}
echo ${b[*]}

答案 3 :(得分:0)

假设您的数据位于文件data.txt中;你可以试试这个:

a=($(< data.txt))
b(){ for((i=$1; i<${#a[*]}; i+=2)); do echo -n "${a[$i]} "; done; echo ;}
b 0
b 1

这肯定不是最好的方法,但它有效!

答案 4 :(得分:0)

您也可以尝试使用xargs first

“按摩”输入
while read a b
do 
  A+=($a) B+=($b)
done < <( xargs -n2 < file )

printf "%s\n" "${A[*]}" "${B[*]}"

-

while read a; read b; do
  read; read;
  A+=($a) B+=($b)
done < file

printf "%s\n" "${A[*]}" "${B[*]}"

答案 5 :(得分:0)

使用一次调用awk:

awk 'BEGIN{RS="\n\n\n"}{A=A " " $1;B=B " " $2}END{printf A "\n" B "\n"}' NewFile

仅使用posix shell(带内置)

#!/bin/sh
L=""
R=""
while read A && read B && read dummy && read dumtwo || [ "$A" ];do
    L="$L $A"
    R="$R $B"
done < NewFile
echo $L
echo $R

注意:不是将变量存储在字符串$ L和$ R中,而是使用bash数组而不是使用L_ARRAY + =(“$ A”)或者像这样:

#!/bin/bash
L=()
R=()
while read A && read B && read dummy && read dumtwo || [ "$A" ];do
    L[${#L[@]}]=${A}
    R[${#R[@]}]=${B}
done < NewFile
echo -e "${L[@]}\n${R[@]}"

或使用sed(2个电话)

L=`sed -n 1~4p NewFile`
R=`sed -n 2~4p NewFile`
echo $L
echo $R