2014-09-11 630 views
4

我看過類似這樣的問題,但在這種情況下似乎沒有任何解決方案可行。我有一個文本文件,它看起來像這樣使用bash shell腳本在2個字符串之間提取字符串

START-OF-FILE 
RUNDATE=20140910 
FIRMNAME=dl 
FILETYPE=pc 
REPLYFILENAME=TEST 
DERIVED=yes 
PROGRAMFLAG=oneshot 
SECID=ISIN 
SECMASTER=yes 
PROGRAMNAME=getdata 
START-OF-FIELDS 
ISSUER 
START-OF-DATA 
US345370CN85|0|4|FORD MOTOR COMPANY|FORD MOTOR COMPANY| | | 
US31679BAC46|0|4|FIFTH STREET FINANCE COR|FIFTH STREET FINANCE COR| | | 
END-OF-DATA 
END-OF-FILE 

我試圖寫一個bash shell腳本只提取「START-OF-DATA」和「END-OF-DATA」排除兩者之間的文本這些。所以輸出我要找的應該是這樣的

US345370CN85|0|4|FORD MOTOR COMPANY|FORD MOTOR COMPANY| | | 
US31679BAC46|0|4|FIFTH STREET FINANCE COR|FIFTH STREET FINANCE COR| | | 

到目前爲止,我寫的代碼看起來像這樣

while read line 
do 
    name=$line 

    echo $name | sed -e 's/START-OF-DATA\(.*\)END-OF-DATA/\1/' 

done < $1 

和慶典像

./script.sh file.txt 

那裏運行它script.sh是我保存的shell腳本,而file.txt是它讀取的文本文件。目前它只讀取和回顯整個文件。我猜我的語法有點傻。任何在正確的方向指針將不勝感激。 感謝

回答

5

使用awk你可以這樣做:

awk '/START-OF-DATA/{p=1;next} /END-OF-DATA/{p=0;exit} p' file 
US345370CN85|0|4|FORD MOTOR COMPANY|FORD MOTOR COMPANY| | | 
US31679BAC46|0|4|FIFTH STREET FINANCE COR|FIFTH STREET FINANCE COR| | | 

或者使用sed

sed -n '/START-OF-DATA/,/END-OF-DATA/{/START-OF-DATA\|END-OF-DATA/!p;}' file 
US345370CN85|0|4|FORD MOTOR COMPANY|FORD MOTOR COMPANY| | | 
US31679BAC46|0|4|FIFTH STREET FINANCE COR|FIFTH STREET FINANCE COR| | | 
+1

太好了。正是我在找什麼......你們很快就掉了標記我必須說:)再次感謝 – tasslebear 2014-09-11 11:47:47

2

爲了使您的解決方案工作,你可以做一個標記,當你點擊「START-OF- DATA「讀取」True「(或類似),然後在您點擊」數據結束「時結束。使用此標記可以指示回顯打印標記爲「真」(當您位於相關文本塊內時)。

...或者你可以使用SED:

sed -n '/START-OF-DATA/,/END-OF-DATA/ { //!p }' file.txt 
+0

感謝您的回覆bryn。您的解決方案完美運作由於他的回覆速度更快,我不得不贊同@anubhava。不過謝謝。現在腳本工作正常。問候 – tasslebear 2014-09-11 11:52:42

+0

您好bryn。你的[tag:sed]命令行比[anubhava的一個]更好(http://stackoverflow.com/a/25786380/938111)。但對我來說有點神祕:我想知道'{// p}'中的'//'意味着什麼。請給出一些解釋或鏈接到網站解釋這一點。乾杯;-) – olibre 2014-09-12 08:49:56

1

我想補充Perlish的grep方式,如前所述here

grep -Pzo "(?s)START-OF-DATA.*END-OF-DATA" "$1" 

這仍然包括START-OF-DATAEND-OF-DATA標記。要擺脫他們,該模式有可能成爲一個有點不太可讀:

grep -Pzo "(?s)(?<=START-OF-DATA\n).*(?=\nEND-OF-DATA)" 

(?<=START-OF-DATA\n)(?=\nEND-OF-DATA)環視斷言在perlre描述,即它們用於匹配,但不包括在結果。

+1

不錯,使用準備,但是行開始數據和數據結束被打印:/請嘗試改進你的命令行,以避免打印這兩行。玩得開心:-)乾杯 – olibre 2014-09-11 12:29:07

+1

@olibre:感謝您指出。我添加了改進的命令行。 – 2014-09-11 16:53:25