我在由两条空行分隔的单列中有正或负浮点值的数据。
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
在理想情况下,该解决方案不仅适用于数字,还适用于以类似方式分隔的文本。
怎么样:
$ 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
格式化输出。
这可能对您有用(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 的内容。这是一个更长但更易读的解决方案:
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[*]}
假设您的数据在文件 data.txt 中;你可以试试这个:
a=($(< data.txt))
b(){ for((i=$1; i<${#a[*]}; i+=2)); do echo -n "${a[$i]} "; done; echo ;}
b 0
b 1
这当然不是最好的方法,但它确实有效!
您也可以尝试使用“按摩”输入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[*]}"
使用一次对 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
注意:您可以使用 bash 数组而不是使用 L_ARRAY+=("$A") 或像这样存储变量,而不是将变量存储在字符串 $L 和 $R 中:
#!/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