web-dev-qa-db-fra.com

Comment utiliser sed pour extraire une sous-chaîne

J'ai un fichier contenant les lignes suivantes:

  <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>

Je veux exécuter la commande sur ce fichier pour extraire uniquement les noms de paramètre tels qu'ils apparaissent dans la sortie suivante:

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

Quelle pourrait être cette commande?

44
MOHAMED

Vous voulez awk.

Ce serait un hack rapide et sale:

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

PortMappingEnabled
PortMappingLeaseDuration
RemoteHost
ExternalPort
ExternalPortEndRange
InternalPort
PortMappingProtocol
InternalClient
PortMappingDescription
33
Chris

grep est né pour extraire des choses:

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

tester avec vos données:

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
81
Kent

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

fait le travail.

54
unxnut

Vous ne devez pas analyser XML à l'aide d'outils tels que sed ou awk. C'est sujet aux erreurs.

Si l'entrée change, et avant le paramètre name, vous obtiendrez un caractère de nouvelle ligne au lieu d'un espace, il échouera un jour et produira des résultats inattendus.

Si vous êtes vraiment sûr que votre entrée sera toujours formatée de cette façon, vous pouvez utiliser cut. C'est plus rapide que sed et awk:

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

Il sera préférable de l’analyser d’abord et d’extraire uniquement l’attribut name:

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

Pour en savoir plus sur xpath, consultez ce tutoriel: http://www.w3schools.com/xpath/

16
Michał Šrajer

Expliquant comment utiliser cut:

cat yourxmlfile | cut -d'"' -f2

Il "coupera" toutes les lignes du fichier en fonction de "d élimiter, et prendra le 2 nd f ield, qui est ce que tu voulais.

5
Rushi Agrawal