[英]Split lines delimited by string into new files as columns Bash script
我有一個如下的數據文件:
>> cat file1.txt
@target G0.S0
1 6
1 4
4 2
@target G0.S0
2 4
8 9
5 7
@target G0.S0
3 5
0 9
3 7
我想在一個新文件中創建由@target G0.S0
分隔的拆分列,其中列設置一個緊挨着前面的列,如下所示:
>> cat file2.txt
1 6 2 4 3 5
1 4 8 9 0 9
4 2 5 7 3 7
我在 inte.net 中搜索,但沒有得到我想要的。
帶有pr
、 grep
和帶有 shell 的tail
的快速單行代碼。
pr "-$(grep -Fc '@target G0.S0' file1.txt)ts"' ' file1.txt | tail -n +2
將 output 重定向到新文件。
pr ... > file2.txt
讓我們分解一下。
pr
是一個打印實用程序。grep -Fc '@target G0.S0' file1.txt
擴展為數字請參閱: grep --help | grep -E -- ' -(F|c)'
grep --help | grep -E -- ' -(F|c)'
$( )
稱為命令替換。t
和s
是pr
的選項,請參閱: pr --help | grep -E -- '^ *-(s|t)'
pr --help | grep -E -- '^ *-(s|t)'
tail
從第二行開始打印,參見: tail --help | grep -- -n
tail --help | grep -- -n
pr -Nts' '
,其中N
是一個整數/數字。 正如@Socowi
所提到的,它有很多限制。 該代碼假設@target G0.S0
之間的所有行都是相等/相同數量的行,在本例中為@target G0.S0
之間的 3 行。 (這是我基於答案的地方),如果(長數據/輸入)大小太多,則應添加一個附加選項,即-w
。 就像我提到的,如果文件/數據/大小/輸入很大/很大,那么首選awk
解決方案。
awk
代替。使用awk
,假設步幅為 4 並將腳本命名為concat
並授予其執行權限:
#! /usr/bin/awk -vN=4 -f
(NR-1)%N==0 {next}
{i=int(NR-2)%N;a[i]=(a[i] ? a[i] " " : "") $0}
END {for (i=0; i<N; i++){print a[i]}}
然后
./concat file1.txt > file2.txt
給
1 6 2 4 3 5
1 4 8 9 0 9
4 2 5 7 3 7
在file2.txt
中
單awk
程序解決方案
以下建議將行累積到一個數組中,該數組通過引用行號進行索引(用於循環索引 1-3 的遞減和余數除法,存儲行 2-4、6-8、10-12 等,每次連接)。 主塊之前的條件不包括第 1、5、9 行等。END 塊迭代數組以打印 output,它被重定向到所需的新文件名。
awk ' (NR-1)%4!=0{lines[(NR-1)%4]=lines[(NR-1)%4]$0}
END{ for(line=1; line<4; line++) {print lines[line]}
} ' file1.txt > file2.txt
這可能對你有用(csplit、粘貼和 sed):
csplit -qz --suppress file '/@target/' '{*}' && paste -d' ' xx* |
sed 's/ / /g' >outFile && rm xx*
將輸入文件拆分為連續編號的文件,每行包含要追加的每一列。
粘貼中間文件,以空格分隔。
從上面的 output 中取出額外的空格, output 到最終文件並清理。
一個 GNU sed 唯一的解決方案:
sed -nE '/\n/!{:a;N;$!ba}
s/^@/\n@/;s/\S$/& /mg;tb
:b;s/^([^\n]*)((\n[^@]*)*)\n@[^\n]*\n([^\n]+)/\1\4\2\n/;tb
s/ \n/\n/;P;s/\n+$//;s/\n\n/\n@\n/g;D' file
如果文件沒有被 slurp 到模式空間(內存),則 slurp 文件。
在模式空間的開頭引入一個換行符,並在每行的末尾提供一個空格。
遍歷文件,將 header 行之后的第一行中的值附加到模式空間的第一行。 替換每個 header,因為它由兩個換行符處理。
刪除行尾引入的空格並打印模式空間的第一行。
如果所有行都已處理,則模式空間的末尾將僅包含換行符,在這種情況下將其刪除。
否則,通過在每次出現的兩個換行符之間插入一個@
來重新引入偽 header。
如果還有要處理的行,則刪除打印的行並再次開始 sed 過程。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.