2つの空の行で区切られた単一の列に正または負の浮動小数点値のデータがあります。
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}
2 行目は、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[*]}
入力を「マッサージ」することもできます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 への 1 回の呼び出しを使用する:
awk 'BEGIN{RS="\n\n\n"}{A=A " " $1;B=B " " $2}END{printf A "\n" B "\n"}' NewFile
posix シェルのみを使用 (ビルトインを使用)
#!/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 に格納するのではなく、L_ARRAY+=("$A") を使用するか、次のように bash 配列を使用できます。
#!/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
データがファイル data.txt にあるとします。あなたはこれを試すことができます:
a=($(< data.txt))
b(){ for((i=$1; i<${#a[*]}; i+=2)); do echo -n "${a[$i]} "; done; echo ;}
b 0
b 1
これは確かに最善の方法ではありませんが、うまくいきます!