2013-05-21 12 views
24

Mam plik zawierający następujące wiersze:Jak korzystać sed wyodrębnić podciąg

<parameter name="PortMappingEnabled" access="readWrite" type="xsd:boolean"></parameter> 
    <parameter name="PortMappingLeaseDuration" access="readWrite" activeNotify="canDeny" type="xsd:unsignedInt"></parameter> 
    <parameter name="RemoteHost" access="readWrite"></parameter> 
    <parameter name="ExternalPort" access="readWrite" type="xsd:unsignedInt"></parameter> 
    <parameter name="ExternalPortEndRange" access="readWrite" type="xsd:unsignedInt"></parameter> 
    <parameter name="InternalPort" access="readWrite" type="xsd:unsignedInt"></parameter> 
    <parameter name="PortMappingProtocol" access="readWrite"></parameter> 
    <parameter name="InternalClient" access="readWrite"></parameter> 
    <parameter name="PortMappingDescription" access="readWrite"></parameter> 

Chcę wykonać polecenia na tym pliku, aby wyodrębnić tylko nazwy parametrów jak pokazano w poniższym wyjściowa:

$sedcommand file.txt 
PortMappingEnabled 
PortMappingLeaseDuration 
RemoteHost 
ExternalPort 
ExternalPortEndRange 
InternalPort 
PortMappingProtocol 
InternalClient 
PortMappingDescription 

Co to może być to polecenie?

+1

Zauważ, że będziesz smutny, gdy ten XML pojawi się w wielu liniach lub gdy zmieni się kolejność argumentów. Jeśli to w ogóle możliwe, spróbuj zajrzeć do odpowiedniego parsera XML. –

+0

Hm, podwójny standard z pytaniami, na które można odpowiedzieć w 10 sekund, a które wymagają więcej czasu? Gdzie jest post zadający pytanie, co próbujesz? Oh poczekaj ... – rliu

Odpowiedz

24

Chcesz awk.

Byłby to szybki i brudny Hack:

awk -F "\"" '{print $2}' /tmp/file.txt

PortMappingEnabled 
PortMappingLeaseDuration 
RemoteHost 
ExternalPort 
ExternalPortEndRange 
InternalPort 
PortMappingProtocol 
InternalClient 
PortMappingDescription 
+0

'cut' zrobi to szybciej :-) –

36

sed 's/[^"]*"\([^"]*\).*/\1/'

spełnia swoje zadanie.

+6

+1 Ładne, proste i eleganckie !!! Kocham to!!! – Barranka

+32

To nie jest proste ani eleganckie. Po prostu tajemniczy. – Stefan

+11

@Stefan, być może dla niewprawnego oka. Ale spędzaj czas z RegEx i jak jazz lub Picasso, docenisz proste piękno. – SaxDaddy

64

grep urodził wydobyć rzeczy:

grep -Po 'name="\K[^"]*' 

testy z danymi:

kent$ echo '<parameter name="PortMappingEnabled" access="readWrite" type="xsd:boolean"></parameter> 
    <parameter name="PortMappingLeaseDuration" access="readWrite" activeNotify="canDeny" type="xsd:unsignedInt"></parameter> 
    <parameter name="RemoteHost" access="readWrite"></parameter> 
    <parameter name="ExternalPort" access="readWrite" type="xsd:unsignedInt"></parameter> 
    <parameter name="ExternalPortEndRange" access="readWrite" type="xsd:unsignedInt"></parameter> 
    <parameter name="InternalPort" access="readWrite" type="xsd:unsignedInt"></parameter> 
    <parameter name="PortMappingProtocol" access="readWrite"></parameter> 
    <parameter name="InternalClient" access="readWrite"></parameter> 
    <parameter name="PortMappingDescription" access="readWrite"></parameter> 
'|grep -Po 'name="\K[^"]*' 
PortMappingEnabled 
PortMappingLeaseDuration 
RemoteHost 
ExternalPort 
ExternalPortEndRange 
InternalPort 
PortMappingProtocol 
InternalClient 
PortMappingDescription 
+4

Po prostu FYI, ze strony podręcznika grep dotyczącego '-P':" To jest wysoce eksperymentalne i ** grep -P ** może ostrzegać o niezaimplementowanych funkcjach. " –

+0

Nie wszystkie * nix distros obsługują "grep -o". Jedną z takich instancji, o której mi wiadomo, jest AIX –

+0

@ FukuzawaYukio Myślę, że grep dostarczany przez Ubuntu Linux powinien go wspierać, prawda? mimo że nie jestem użytkownikiem ubuntu. Pytanie zostało oznaczone jako Linux & ubuntu, a nie jako Unix lub Aix. Ale twój komentarz jest poprawny. – Kent

12

Nie należy analizować XML przy użyciu narzędzi takich jak sed, awk lub. Jest podatny na błędy.

Jeśli dane wejściowe ulegną zmianie, a przed parametrem nazwy pojawi się znak nowego wiersza zamiast spacji, pewnego dnia nie uda się uzyskać nieoczekiwanych wyników.

Jeśli jesteś naprawdę pewien, że twoje dane wejściowe będą zawsze formowane w ten sposób, możesz użyć cut. Jest szybszy niż sed i awk:

cut -d'"' -f2 < input.txt 

Będzie lepiej najpierw przeanalizować je i wyodrębnić tylko atrybut name parametr:

xpath -q -e //@name input.txt | cut -d'"' -f2 

aby dowiedzieć się więcej o XPath, zobacz ten samouczek: http://www.w3schools.com/xpath/

Powiązane problemy