반복하지 않고 한 문자열에서 구분 기호 사이에 하위 문자열을 여러 번 가져오기

반복하지 않고 한 문자열에서 구분 기호 사이에 하위 문자열을 여러 번 가져오기

이에 대한 해결책을 찾기 위해 여기저기 찾아보았지만 찾을 수 없었습니다.

나는 qstat -x많은 양의 직업 정보를 전달하는 데 사용하고 있습니다. 출력은 qstat -xXML 형식입니다. 내가 찾고 있는 하위 문자열은 두 개의 명시적인 구분 기호 <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|^$)'

tr 대신 sed를 사용하여 버전 2와 거의 동일한 작업을 수행합니다.

편집: 또한 ^$원하지 않는 개행 문자를 반환하지 않도록 grep 검색 문자열에 추가했습니다.

Edit2: OP를 변경하신 것으로 보입니다. 위의 답변은 원래 질문에 대한 것입니다. 아래에서는 도움이 될 수 있는 스크립트를 만들었습니다. http://pastebin.com/uKWAGE0Y

관련 정보