我已经到处寻找解决这个问题的方法,但我找不到。
我用来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
。我尝试使用awk
、grep
和的变体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