2016-01-20 70 views
0

我有一個巨大的行是從ws的響應,我需要得到所有在<asunto></asunto>之間的字符串。該文件是這樣的:HUGE行之間的AWK/SED提取字符串

Content-Type: application/xop+xml; charset=UTF-8; type="application/soap+xml"; 
Content-Transfer-Encoding: binary 
Content-ID: <[email protected]> 

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Body><ns1:consultarComunicacionesResponse xmlns:ns1="http://ve.tecno.afip.gov.ar/domain/service/ws"><ns2:RespuestaPaginada xmlns:ns2="http://ve.tecno.afip.gov.ar/domain/service/ws" xmlns:ns3="http://core.tecno.afip.gov.ar/model/ws/types" xmlns:ns4="http://ve.tecno.afip.gov.ar/domain/service/ws/types"><pagina>1</pagina><totalPaginas>1</totalPaginas><itemsPorPagina>100</itemsPorPagina><totalItems>2</totalItems><ns4:items><ns4:ComunicacionSimplificada><idComunicacion>sdfgsfdgsfdgsd</idComunicacion><cuitDestinatario>sdfgsdfgsdfgsfdg</cuitDestinatario><fechaPublicacion>sdfgsdfg</fechaPublicacion><fechaVencimiento>sdfgsdfgsdfg</fechaVencimiento><sistemaPublicador>sdfgsdfgsfg</sistemaPublicador><sistemaPublicadorDesc>sdfgsdfggf</sistemaPublicadorDesc><estado>2</estado><estadoDesc>sdfgsdfgsgf</estadoDesc><asunto>EXAMPLEEEEEEEEEEEEEEEE1</asunto><prioridad>3</prioridad><tieneAdjunto>sdfgfdg</tieneAdjunto></ns4:ComunicacionSimplificada><ns4:ComunicacionSimplificada><idComunicacion>sdfgsdfgdfg</idComunicacion><cuitDestinatario>sdfgdfsg</cuitDestinatario><fechaPublicacion>sdfgsdfg</fechaPublicacion><fechaVencimiento>sdfgdsfg</fechaVencimiento><sistemaPublicador>sdfgsdfg</sistemaPublicador><sistemaPublicadorDesc>sdfgsdfgdsfggsdf</sistemaPublicadorDesc><estado>1</estado><estadoDesc>dsfgsdfgsgd</estadoDesc><asunto>EXAMPLEEEEEEEEEEEEEEEE2</asunto><prioridad>asdfdsf</prioridad><tieneAdjunto>asdfasdf</tieneAdjunto></ns4:ComunicacionSimplificada></ns4:items></ns2:RespuestaPaginada></ns1:consultarComunicacionesResponse></soap:Body></soap:Envelope>  

我shuold得到這樣的:

EXAMPLEEEEEEEEEEEEEEEE1  
EXAMPLEEEEEEEEEEEEEEEE2 

可能有大量的重複,0和數百間。

謝謝!

回答

0

awk來救援!

$ awk -v RS='[<>]' '/\/asunto/{f=0;next} f; /asunto/{f=1}' file 

EXAMPLEEEEEEEEEEEEEEEE1 
EXAMPLEEEEEEEEEEEEEEEE2 

更新:根據該意見,如果有機會的話,標籤在其它地方存在,您可以在打開/關閉標籤的左邊和右邊錨

$ awk -v RS='[<>]' '/^\/asunto$/{f=0;next} f; /^asunto$/{f=1}' file 
EXAMPLEEEEEEEEEEEEEEEE1 
EXAMPLEEEEEEEEEEEEEEEE2 

或者等價地,檢查一個確切的字符串匹配

$ awk -v RS='[<>]' '$0=="/asunto"{f=0;next} f; $0=="asunto"{f=1}' file 
EXAMPLEEEEEEEEEEEEEEEE1 
EXAMPLEEEEEEEEEEEEEEEE2 

也注意到,並非所有的awk變種支持多焦RS。

+1

你應該提到它的呆子特有由於多焦RS,它會失敗,如果'asunto'出現在其他上下文中而不是標籤。 –

+0

@karakfa - 爲了解決Ed的第二點,你可以稍微改變一行:awk -v RS ='[<>]''/ \/asunto * $/{f = 0; next} f;/^ asunto/{f = 1}'文件'? – peak

+0

是的,謝謝,我明白你的意思。更新。 – karakfa

1

您也可以使用GNUgrep

grep -oP '(?<=<asunto>)((?!</asunto>).)+(?=</asunto>)' yourfile 

這需要回顧後先行的優勢。

Here's其內部的一個很好的解釋。

性能

$ wc -l bigfile 
100000 bigfile 

$ time awk -v RS='</?asunto>' '!(NR%2)' bigfile >/dev/null 

real 0m0.277s 
user 0m0.254s 
sys 0m0.022s 


$ time grep -oP '(?<=<asunto>)((?!</asunto>).)+(?=</asunto>)' bigfile >/dev/null 

real 0m4.318s 
user 0m4.292s 
sys 0m0.020s 

$ time awk -v RS='[<>]' '/\/asunto/{f=0;next} f; /asunto/{f=1}' bigfile >/dev/null 

real 0m7.088s 
user 0m6.928s 
sys 0m0.021s 

@Ed代碼迄今爲止取得的最大性能。

1

隨着GNU AWK多焦RS:

$ awk -v RS='</?asunto>' '!(NR%2)' file 
EXAMPLEEEEEEEEEEEEEEEE1 
EXAMPLEEEEEEEEEEEEEEEE2 
+1

迄今爲止最大的表現! – klashxx

0

使用XML解析器(和awk去除頭)

awk -v RS= 'NR>1' ws.out | xmlstarlet sel -t -v //asunto -n 
0

這可能會爲你工作(GNU SED):

sed -nr '/<asunto>([^<]*)<\/asunto>/{s//\n\1\n/;s/[^\n]*\n//;P;D}' file 

這會將字符串縮減爲預​​定行然後打印,刪除此行並重復。不包含所需字符串的行將被忽略。

0

正如其他地方指出的那樣,XML感知工具原則上會更安全,但如果沒有嵌套「asunto」標記,以下GNU grep咒語可能會有用,並且即使在<asunto></asunto>爲空或包含其他標籤:

grep -oP '(?<=<asunto>).*?(?=</asunto>)' 

這裏的關鍵是,非貪婪的子表達式:.*?

相關問題