2014-08-29 35 views
2

我試圖在bash中最後一次發生字符串後添加一個新行。在bash中最後一次發生字符串後插入新行

舉例來說,如果我有以下文字:

GG1 test-35 
GG1 test-38 
GG1 test-40 

HH1 test-52 
HH1 test-60 
HH1 test-32 
HH1 test-40 

LL1 test-101 
LL1 test-99 
LL1 test-24 

說我想在「HH」塊的末尾添加一個新行,所以它會變成:

HH1 test-52 
HH1 test-60 
HH1 test-32 
HH1 test-40 
HH1 test-56 

到目前爲止,我已經嘗試過使用sed和awk,但似乎無法做到。如果我可以搜索一個實際的測試編號,比如HH1 test-40,這很容易,但我可以搜索的唯一東西就是首字母縮寫詞。所以我需要HH1的最後一行,然後在它後面添加一個新行。

感謝任何幫助。

+0

你想只打印HH1塊還是整個文件? – 2014-08-29 11:29:18

+0

整個文件,它只是有新的包括HH1測試線-56 – user3722194 2014-08-29 11:30:09

+0

什麼是輸入? 'test-56'添加到塊XX或直接'HH1 test-56'添加到一個塊(或創建一個新塊) – NeronLeVelu 2014-08-29 11:41:36

回答

3

快速&髒GAWK:

awk 'BEGIN{RS="";ORS="\n\n"}/^HH/{$0=$0"\nHH1 test-56"}7' file 

這是骯髒的,因爲它的葉子在輸出端的空行。

+0

應該與任何POSIX awk一起工作,而不僅僅是gawk .. – Scrutinizer 2014-08-29 11:42:47

+0

它不會工作if最後一個'HH1'後面沒有空行。 – 2014-08-29 11:59:37

+0

@AvinashRaj OP說'HH塊'。我的解決方案來自我對問題和OP的例子的理解。 – Kent 2014-08-29 12:11:56

1

有一個選項LOT:

awk '/HH/{seen++} seen && !/HH/{print "HH1 test-56"; seen=0} 1' file 

或:

tac file | awk '/HH/ && !seen{print "HH1 test-56"; seen++} 1' | tac 

或:

awk 'NR==FNR{if (/HH/) nr=NR; next} 1; FNR==nr{print "HH1 test-56"}' file file 

或(GAWK - 僅適用於多字符RS):

gawk -v RS='^$' -v ORS= '{sub(/.*HH[^\n]+\n/,"&HH1 test-56\n")} 1' file 

或....

0
LineToAdd="HH1 test-56" 
{ echo "${LineToAdd}"; cat YourFile; } | sed -n '1x;H;${x 
    s/^\([^ ]\{3\}\) \([^[:cntrl:]]*\)\(\n\)\(.*\)\1 \([^[:cntrl:]]*\)\3/\4\1 \5\3\1 \2\3/ 
    s/^\n// 
    p 
    }' 

解釋

  • 外接線來在內容開始添加(可以通過在結束添加完成,一些代碼addapt)
  • 負載所有在緩衝區中的行
  • 移動(以刪除組地址)第2行第1行(因此第1組爲HH1,測試-56爲第2組)在最後一行有第1組。(這裏是快速和骯髒的假設存在沒有HH1下面一行的內容)
  • 刪除第一行,如果新線(快速和骯髒的同時,假設原始文件不會用新行開始)
  • 打印結果 -
1

還有一個AWK 應在所有awks工作

awk 'a=/^HH/{b=1}b&&!a{print "HH1 test-56";b=0}1' file 

awk -F- 'a=/HH/{b=$1}b&&!a{print b"-56";b=0}1' file 
0

該perl命令將最後HH1行之後添加一個新行的下方,

perl -0777pe 's/(?s)(?<=HH1\stest-)(\d+\n)(?=(?:(?!HH1\stest-).)*$)/\1HH1 test-56\n/' file 

實施例:

$ cat file 
HH1 test-52 
HH1 test-60 
HH1 test-32 

LL1 test-101 
LL1 test-99 
HH1 test-40 
LL1 test-24 

$ perl -0777pe 's/(?s)(?<=HH1\stest-)(\d+\n)(?=(?:(?!HH1\stest-).)*$)/\1HH1 test-56\n/' file 
HH1 test-52 
HH1 test-60 
HH1 test-32 

LL1 test-101 
LL1 test-99 
HH1 test-40 
HH1 test-56 
LL1 test-24 
0

小bash腳本還可以提供您正在尋找的靈活性和字符串添加:

#!/bin/bash 

## Usage: 
# 
# ./scriptname datafile [new-sting-to-add (HH1 test-56)] [string-to-search (HH1)] 

newstr="${2:-HH1 test-56}"   # set newstr 
srchstr="${3:-"${newstr// */}"}" # set srchstr 
found=1        # set found flag to false 

# read datafile line-by-line 
while read pfx tststr || [ -n "$tststr" ] ; do 
    [ "$pfx" == "$srchstr" ] && found=0     # if pfx matches set flag 
    [ $found -eq 0 ] && [ "$pfx" != "$srchstr" ] && { # if flag and no match 
     echo "$newstr"         # add newstr to output 
     found=1           # reset flag to false 
    } 
    echo "$pfx $tststr"    # normal output 

done <"$1" 

輸出:

$ ./hh.sh dat/hh.dat # (using default values) 
GG1 test-35 
GG1 test-38 
GG1 test-40 

HH1 test-52 
HH1 test-60 
HH1 test-32 
HH1 test-40 
HH1 test-56 

LL1 test-101 
LL1 test-99 
LL1 test-24 
1

這可能會爲你工作(GNU sed的&擊):

sed '/^HH1/!b;:a;n;//ba;i\HH1 test-56' file 

如果線路沒有開始HH1打印正常,否則打印,直到該行不會開始HH1,然後插入換行符。

相關問題