從一個字串中多次取得分隔符號之間的子字串而不循環

從一個字串中多次取得分隔符號之間的子字串而不循環

我已經到處尋找解決這個問題的方法,但我找不到。

我用來qstat -x傳遞一長串工作訊息。輸出qstat -x為 XML 格式。我正在尋找的子字串位於兩個顯式分隔符號<Output_Path>和之間</Output_Path>。以下是 的一些輸出範例qstat -x,敏感資訊已被刪除:

<Data><Job><Job_Id>4382.xxxxxxxx.xx.xxxxxxx</Job_Id><Job_Name>r053_x.xxMx.xxR_400k_neos2.pbs</Job_Name><Job_Owner>[email protected]</Job_Owner><job_state>H</job_state><queue>default</queue><server>xxxxxxxx.xx.xxxxxxx</server><Checkpoint>u</Checkpoint><ctime>1466396941</ctime><Error_Path>xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r053_x.xxMx.xxR_400k_neos2/r053_x.xxMx.xxR_400k_neos2.pbs.e4382</Error_Path><Hold_Types>u</Hold_Types><Join_Path>n</Join_Path><Keep_Files>n</Keep_Files><Mail_Points>a</Mail_Points><mtime>1466423857</mtime><Output_Path>xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r053_x.xxMx.xxR_400k_neos2/r053_x.xxMx.xxR_400k_neos2.pbs.o4382</Output_Path><Priority>0</Priority><qtime>1466396941</qtime><Rerunable>True</Rerunable><Resource_List><cput>9999:59:59</cput><nodect>1</nodect><nodes>1:ppn=12:gpus=1</nodes><walltime>2400:00:00</walltime></Resource_List><comment>Not Running: Not enough of the right type of nodes are available</comment><submit_args>r053_x.xxMx.xxR_400k_neos2.pbs</submit_args><fault_tolerant>False</fault_tolerant><job_radix>0</job_radix><submit_host>xxxxxxxx.xx.xxxxxxx</submit_host></Job><Job><Job_Id>4396.xxxxxxxx.xx.xxxxxxx</Job_Id><Job_Name>0R_20k_neos2.pbs</Job_Name><Job_Owner>[email protected]</Job_Owner><job_state>H</job_state><queue>default</queue><server>xxxxxxxx.xx.xxxxxxx</server><Checkpoint>u</Checkpoint><ctime>1466606895</ctime><Error_Path>xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r061_x.xxMx.xxR_20k_neos2/0R_20k_neos2.pbs.e4396</Error_Path><Hold_Types>u</Hold_Types><Join_Path>n</Join_Path><Keep_Files>n</Keep_Files><Mail_Points>a</Mail_Points><mtime>1466609370</mtime><Output_Path>xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r061_x.xxMx.xxR_20k_neos2/0R_20k_neos2.pbs.o4396</Output_Path><Priority>0</Priority>

我想獲取<Output_Path>和的每次迭代之間存在的所有子字串</Output_Path>。也就是說,如果我有字串

<Output_Path>xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r061_x.xxMx.xxR_20k_neos2/0R_20k_neos2.pbs.o4396</Output_Path><Output_Path>xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r053_x.xxMx.xxR_400k_neos2/r053_x.xxMx.xxR_400k_neos2.pbs.o4382</Output_Path>

我想要一個返回的命令

xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r061_x.xxMx.xxR_20k_neos2/0R_20k_neos2.pbs.o4396
xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r053_x.xxMx.xxR_400k_neos2/r053_x.xxMx.xxR_400k_neos2.pbs.o4382

或者

xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r061_x.xxMx.xxR_20k_neos2/0R_20k_neos2.pbs.o4396 xxxxxxxx.xx.xxxxxxx:/data/xxxxxxxx/xxxxxxxxxxx/summer2016/relax/r053_x.xxMx.xxR_400k_neos2/r053_x.xxMx.xxR_400k_neos2.pbs.o4382

但我需要在不使用任何慢循環的情況下完成它for。我嘗試使用awkgrep和的變體sed,但找不到任何有效的方法。

有任何想法嗎?

答案1

試試這個,然後:

xmlstarlet sel -t -v //Output_Path -nl data.xml

答案2

如果你的系統的 grep 支援 PCRE,你也許可以這麼做

$ echo 'aaa string1 bbb aaa string2 bbb aaa string3 bbb' | 
  grep -oP '(?<=(aaa|bbb) )\w*?(?= (aaa|bbb))'
string1
string2
string3

或者如果您需要處理更一般數量的周圍空白

$ echo 'aaa string1 bbb aaa string2 bbb aaa string3 bbb' |
  grep -oP '(aaa|bbb)\s+\K\w*?(?=\s+(aaa|bbb))'
string1
string2
string3

答案3

如果您對以下結構感到滿意:

string1
string2
string3

我只是簡單地將分隔符號替換為換行符。像這樣的事情應該會讓你接近:

sed "s/\(aaa\)\|\(bbb\)/\n/g" test.txt

編輯

正如下面@clk 所指出的,我的第一個答案可能會給出雙換行符。更改為以下內容:

sed "s/\(\s\)\?aaa\(\s\)\?/bbb/g" test.txt | sed "s/b*//g"

對我來說產量:

 string1 string2 string3

當透過管道輸入時,其工作原理也是相同的,例如:

echo 'aaa string1 bbb aaa string2 bbb aaa string3 bbb' | sed "s/\(\s\)\?aaa\(\s\)\?/bbb/g" | sed "s/b*//g"

不是一個非常漂亮的答案,但又快又髒,並為您提供了您所要求的格式。

答案4

僅使用 sed (具有-r擴展正規表示式的標誌)

echo "aaa string1 bbb aaa string2 bbb aaa string3 bbb" | sed -r 's/(aaa|bbb) ?//g'

退貨

string1 string2 string3 

您還可以使用 tr 和 grep (帶有-vE)獲得此版本:

echo "aaa string1 bbb aaa string2 bbb aaa string3 bbb" | tr ' ' '\n'| grep -vE '(aaa|bbb|^$)'

退貨

string1
string2
string3

tr只是用換行符號替換空格字元。 grep -vE使用正規表示式(“E”)並排除符合行(“v”)。

第三個版本使用 sed (不含標誌)和 grep (與上一個版本相同):

echo "aaa string1 bbb aaa string2 bbb aaa string3 bbb" | sed 's/\s/\n/g' | grep -vE '(aaa|bbb|^$)'

做與第二版幾乎完全相同的事情,使用 sed 而不是 tr。

編輯:還在^$grep 搜尋字串中加入了 ,以確保它不會傳回不需要的換行符。

Edit2:我看到你改變了OP。以上答案是對原始問題的回答。下面我編寫了一個可能對您有幫助的腳本: http://pastebin.com/uKWAGE0Y

相關內容