반복 없이 문자열에서 구분 기호 사이의 하위 문자열을 여러 번 가져옵니다.

반복 없이 문자열에서 구분 기호 사이의 하위 문자열을 여러 번 가져옵니다.

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

나는 그것을 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>sum 의 각 반복 사이에 존재하는 모든 하위 문자열을 얻고 싶습니다 </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 

-vEtr 및 grep을 사용하여 이 버전을 얻을 수도 있습니다 (다음 포함).

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

관련 정보