簡體   English   中英

將字符串分隔的行拆分為新文件作為列 Bash 腳本

[英]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 中搜索,但沒有得到我想要的。

帶有prgrep和帶有 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)'
  • $( )稱為命令替換
  • tspr的選項,請參閱: 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解決方案。


  • 對於大數據大小/文件,我會用 go 和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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM