我有一個大檔案coord,如下所示:
$coord
-6.81387808414325 5.82189470091282 -1.45477353169903 c f
3.12250219010826 1.39239934150351 0.78451413146001 o f
-4.76572488013335 -1.67551810949494 -1.58797087759328 c f
-0.15061495158492 -2.18614667480844 -2.60227003662941 c f
etc...
9.21060449992324 -2.77968508411378 0.71587738888748 h f
5.87109372056745 -2.67040600177892 0.54514819243204 h f
7.70747476642116 -1.85827163328137 -2.12317155170529 h f
3.16053583847830 1.75657003778612 4.21784993053015 h
3.20523873898751 2.06642906155866 6.03962166222879 o
3.84518636016769 0.52341324778083 6.76769535558585 h
$intdef
# definitions of internal coordinates
1 f 1.0000000000000 stre 6 21 val= 2.05908
2 f 1.0000000000000 stre 6 53 val= 2.07110
3 f 0.0463401612403 bend 53 21 6 val= 1.20720
0.5016372600998 bend 7 21 6
0.4983829790270 bend 7 53 6
etc...
有以$和 $coord開頭的關鍵字$intdef。我想要做的是f從每一行之后洗掉$coord. 所以輸出應該是:
$coord
-6.81387808414325 5.82189470091282 -1.45477353169903 c
3.12250219010826 1.39239934150351 0.78451413146001 o
-4.76572488013335 -1.67551810949494 -1.58797087759328 c
-0.15061495158492 -2.18614667480844 -2.60227003662941 c
etc...
9.21060449992324 -2.77968508411378 0.71587738888748 h
5.87109372056745 -2.67040600177892 0.54514819243204 h
7.70747476642116 -1.85827163328137 -2.12317155170529 h
3.16053583847830 1.75657003778612 4.21784993053015 h
3.20523873898751 2.06642906155866 6.03962166222879 o
3.84518636016769 0.52341324778083 6.76769535558585 h
$intdef
# definitions of internal coordinates
1 f 1.0000000000000 stre 6 21 val= 2.05908
2 f 1.0000000000000 stre 6 53 val= 2.07110
3 f 0.0463401612403 bend 53 21 6 val= 1.20720
0.5016372600998 bend 7 21 6
0.4983829790270 bend 7 53 6
etc...
fs 應該只在關鍵字之后洗掉,而$coord不是在任何其他關鍵字之后。也不應該洗掉任何其他內容。只是fs。所以我可以找到關鍵字$coord并停止洗掉f下一個關鍵字之后的 s 。我試圖在 bash 中做到這一點。我發現我可以洗掉最后一列awk:
awk 'NF{NF=-1};1'
我可以找到其中的f行sed:
sed -n '/$coord/,/\$/{/$coord/!{/\$/!p}}'
我試圖制作一個腳本,但我無法弄清楚如何使用它們來獲得正確的輸出。還是有一些更簡單的方法可以做到這一點?任何人都可以幫忙嗎?
uj5u.com熱心網友回復:
您可以awk為此使用:
awk -v RS='$' -v ORS='$' '/^coord\n/ {gsub(/ f\n/,"\n")} 1' file
uj5u.com熱心網友回復:
這可能對您有用(GNU sed):
sed '/^$./h;G;/^$coord/Ms/f//g;P;d' file
將關鍵字存盤在保留空間中。
將保留空間附加到每一行,如果保留空間以從該行中$coord洗掉任何f's 開頭。
列印模式空間中的第一行,然后洗掉所有內容。
因此,當關鍵字出現時,其后的每一行都將屬于該關鍵字,直到關鍵字發生變化。
該P命令允許按原樣列印當前行,而不是引入的工件。
uj5u.com熱心網友回復:
在sed中,您可以輕松地將命令限制為一系列行。這里唯一的小困難是典型的命令將在匹配的行上進行替換,這里選擇行范圍的最簡單方法是使用不應該發生替換的兩個標題。因此,您可以限制行范圍以排除標題,也可以將要替換的字串從僅f在行尾擴展到 f行尾。您可能無論如何都想洗掉空格,并且您的標題可能包含空格,因此尚不清楚以下哪種解決方案是合適的:
sed '/\$coord/,/^[$]/{/^[^$]/s/f$//;}'
sed '/\$coord/,/^[$]/s/ f$//'
第二種解決方案稍微簡單一些,但不太健壯,因為如果任何一個關鍵字以 f. 如果您的關鍵字不能包含空格,這可能不是問題。第一種解決方案僅從f行尾洗掉 ,并且將保留前導空格。這與您給出的描述一致,但可能不是您真正想要的行為。
兩種解決方案都在做基本相同的事情;將命令s/f$//應用于有限范圍的行。該命令搜索與行尾的a 匹配的模式f$(或) 。在每個命令中,原始地址范圍被指定為(包括)匹配的行(反斜杠導致 sed 匹配文字而不是匹配行尾)和以文字開頭的下一行之間的行。第一種解決方案包括第二個地址范圍,該地址范圍防止命令應用于與關鍵字匹配的行。 f$f$coord$$
uj5u.com熱心網友回復:
使用任何 awk:
$ awk '/^\$/{ key=$0 } key=="$coord"{ sub(/ f$/,"") } 1' file
$coord
-6.81387808414325 5.82189470091282 -1.45477353169903 c
3.12250219010826 1.39239934150351 0.78451413146001 o
-4.76572488013335 -1.67551810949494 -1.58797087759328 c
-0.15061495158492 -2.18614667480844 -2.60227003662941 c
etc...
9.21060449992324 -2.77968508411378 0.71587738888748 h
5.87109372056745 -2.67040600177892 0.54514819243204 h
7.70747476642116 -1.85827163328137 -2.12317155170529 h
3.16053583847830 1.75657003778612 4.21784993053015 h
3.20523873898751 2.06642906155866 6.03962166222879 o
3.84518636016769 0.52341324778083 6.76769535558585 h
$intdef
# definitions of internal coordinates
1 f 1.0000000000000 stre 6 21 val= 2.05908
2 f 1.0000000000000 stre 6 53 val= 2.07110
3 f 0.0463401612403 bend 53 21 6 val= 1.20720
0.5016372600998 bend 7 21 6
0.4983829790270 bend 7 53 6
etc...
順便說一句,在你的問題中,你說:
我發現我可以用 awk 洗掉最后一列:
awk 'NF{NF=-1};1'
但是將 NF 設定為負數是一個語意錯誤,所以我想你可能的意思是:
awk 'NF{NF-=1};1'
但是減少 NF 的效果是每個 POSIX 未定義的行為,即使它確實洗掉了最終欄位(因為它會在某些 awk 中但不會在其他 awk 中),這將通過將所有空格鏈轉換為單個空格來破壞輸入的間距. 所以,我不會那樣做。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/487302.html
