Extraire une partie d'une ligne d'un fichier avec sed

18

Je veux lire une partie d'une ligne d'un fichier. Par exemple:

POP3_SERVER_NAME = localhost

Je veux seulement revenir en localhostutilisant sed.

Ce texte est sur la troisième ligne. Je fais cela pour extraire la ligne:

sed -n '3p' installation.sh

Comment extraire uniquement la localhostpièce?

Mercer
la source

Réponses:

26

awk pourrait être un meilleur outil ici.

$ cat test.dat
LINE 1
LINE 2
POP3_SERVER_NAME = localhost

Recherchez les lignes contenant "POP3_SERVER_NAME"; imprimer le dernier champ. Cela ne dépend pas du fait que POP3_SERVER_NAME soit toujours sur la ligne 3, ce qui est probablement une bonne chose.

$ awk '/POP3_SERVER_NAME/{print $NF}' test.dat
localhost

Selon votre application, vous devrez peut-être rendre l'expression régulière plus stricte. Par exemple, vous souhaiterez peut-être faire correspondre uniquement la ligne commençant par POP3_SERVER_NAME.

$ awk '/^POP3_SERVER_NAME/{print $NF}' test.dat
localhost

L'utilisation de sed est un peu moins intuitive. (Merci, je suis conscient de l'ironie.) Adressez la ligne qui contient POP3_SERVER_NAME n'importe où. Remplacez une chaîne vide pour tout le texte du début de la ligne par l'espace facultatif suivant "=". Imprimez ensuite.

sed -n -e '/POP3_SERVER_NAME/ s/.*\= *//p' test.dat
Mike Sherrill 'Cat Recall'
la source
2
La awkcommande est sympa - mais seulement si vous avez des espaces autour du =. Ça ne marchera pas POP3_SERVER_NAME=localhost.
Marcel Stör
2
@Marcel, vous pouvez changer le délimiteur utilisé par awkdes espaces en quelque chose d'autre en utilisant -F. Par exemple: -F "="servira =de délimiteur dans le cas que vous mentionnez.
mattpr
7

Remplacez la pcommande par une substitution qui supprime la partie indésirable de la ligne.

sed -n '3 s/^[^=]*= *//p' installation.sh

Vous pouvez faire correspondre la ligne par mot clé plutôt que par position.

sed -n 's/^ *POP3_SERVER_NAME *= *//p' installation.sh
Gilles 'SO- arrête d'être méchant'
la source
6

On dirait que vous avez un fichier de configuration. Ce que vous pourriez faire est similaire à ce que suggère Adam Siemeon / slm:

sed -nr 's/[^=]+=\s*(.+)$/\1/p' filename

[^=]ne comprend pas tous les « = » caractères, +indique un ou plusieurs du même type de caractère, ce suivi d'une réelle =, \sles espaces blancs (incluant des onglets \tet de nouvelles lignes \n, \r\net des espaces lisses « », alors que les *moyens de zéro ou plus du même type , les parenthèses capturent ce qui se trouve à l'intérieur pour placer les séquences de caractères correspondantes dans les espaces réservés de remplacement \ 1, \ 2, ..., \ n, $signifie la fin d'une ligne. Cela suit le modèle de remplacement typique de:. s/.../.../modifiersL'option de ligne de commande -rsignifie syntaxe regex étendue (par souci de commodité) et -nsignifie ne rien produire jusqu'à ce que ou sauf demande explicite. Le pmodificateur imprime le résultat.

Vous pouvez faire une recherche globale avec le gmodificateur comme:

sed -nr 's/[^=]+=\s*(.+)$/\1 /pg' filename  # note the space after \1

de sorte que vous obtenez une chaîne séparée par ' '(peut - être \n, \tou qu'avez-vous) que vous pouvez traiter facilement.

Les deux sont valides à condition que vos valeurs précédées de l'équation s'étendent jusqu'à la fin d'une ligne et ne soient pas suivies de commentaires ou d'autres caractères dont la sémantique s'écarte d'une simple "valeur".


Éditer:

Je ne peux pas encore commenter ici les messages des autres. Pour indiquer la ligne, il suffit de passer le numéro de ligne, dans votre cas 3, avant sou avant le début du devis (comme dans vim).

sed -nr '3s/[^=]+=\s*(.+)$/\1/p' filename

Veuillez jeter un œil à info sed. Par exemple, 3.2 et 4.7 vous intéressent particulièrement.

Nicolas
la source
5
echo "POP3_SERVER_NAME = localhost" | sed 's/.*= //'
localhost

Ou si vous avez le contenu dans un fichier:

sed 's/.*= //' somefile.txt
localhost
Adam Siemion
la source
ok, mais j'ai lu dans mon fichier comme ceci: sed -n '3p' installation.sh
Mercer
2
@Mercer - voir les mises à jour que j'ai ajoutées à la réponse.
slm
@Adam Siemion - merci, mais comment indiquer le numéro de ligne?
Mercer
4

Vous pouvez utiliser la commande cut, en définissant le délimiteur sur '=' puis imprimer le deuxième champ comme ceci:

cut -d'=' -f2
anselal
la source
3

Plusieurs façons de le faire, étant donné que votre fichier s'appelle foobar:

Spécifiez le modèle à rechercher:

PAT=POP3_SERVER_NAME

Extraire en utilisant sed

sed -n "/$PAT/p" foobar | sed "s/$PAT = //"

Ou en utilisant sedetcut

sed -n "/$PAT/p" foobar | cut -d' ' -f3
unnut
la source
2

La beauté de Linux / Unix est qu'il y a généralement plus d'une façon d'accomplir quelque chose. Dans le cas de l'op, il existe au moins quatre façons différentes d'extraire le nom du serveur POP du fichier:

  1. grep POP3_SERVER_NAME installation.sh | cut -d'=' -f2
  2. grep POP3_SERVER_NAME installation.sh | awk '{print $3}'
  3. grep POP3_SERVER_NAME installation.sh | sed 's/.*= //'
  4. sed -n 's/^.*POP3_SERVER_NAME = //p' installation.sh
thdoan
la source