J'ai un fichier texte au format suivant:
keyword value
keyword value
...
Où mot-clé est un seul mot et la valeur est tout le reste jusqu'à la fin de la ligne. Je veux lire le fichier à partir d'un script shell, de manière à ce que les valeurs (mais pas les mots-clés) subissent une expansion shell.
Avec sed, il est facile de faire correspondre les mots-clés et les parties de valeur
input='
keyword value value
keyword "value value"
keyword `uname`
'
echo "$input"|sed -e 's/^\([^[:space:]]*\)[[:space:]]\(.*\)$/k=<\1> v=<\2>/'
qui produit
k=<keyword> v=<value value>
k=<keyword> v=<"value value">
k=<keyword> v=<`uname`>
mais alors la question est de savoir comment puis-je intégrer une commande shell dans la partie de remplacement de l'expression sed. Dans ce cas, je voudrais que le remplacement soit \1 `echo \2`
.
Réponses:
Sed standard ne peut pas appeler un shell ( GNU sed a une extension pour le faire , si vous ne vous souciez que de Linux non intégré), vous devrez donc effectuer une partie du traitement en dehors de sed. Il existe plusieurs solutions; tous nécessitent un devis soigné.
On ne sait pas exactement comment vous souhaitez que les valeurs soient développées. Par exemple, si une ligne est
lequel des éléments suivants devrait être la sortie?
Je vais discuter de plusieurs possibilités ci-dessous.
coquille pure
Vous pouvez demander au shell de lire ligne par ligne et de la traiter. Il s'agit de la solution la plus simple et également la plus rapide pour les fichiers courts. C'est la chose la plus proche de votre besoin "
echo \2
":read -r keyword value
définit$keyword
le premier mot délimité par des espaces de la ligne et$value
le reste de la ligne moins les espaces de fin.Si vous souhaitez développer des références de variables, mais pas exécuter des commandes en dehors des substitutions de commandes, placez-les
$value
dans un document ici . Je soupçonne que c'est ce que vous cherchiez vraiment.sed passe dans une coquille
Vous pouvez transformer l'entrée en un script shell et l'évaluer. Sed est à la hauteur, mais ce n'est pas si simple. En fonction de votre
echo \2
exigence " " (notez que nous devons échapper les guillemets simples dans le mot-clé):Pour aller avec un document ici, nous devons toujours échapper au mot-clé (mais différemment).
C'est la méthode la plus rapide si vous avez beaucoup de données: elle ne démarre pas un processus séparé pour chaque ligne.
awk
Les mêmes techniques que nous avons utilisées avec sed fonctionnent avec awk. Le programme résultant est considérablement plus lisible. Aller avec "
echo \2
":Utilisation d'un document ici:
la source
Avec GNU,
sed
vous pouvez utiliser la commande suivante:Quelles sorties:
avec vos données d'entrée.
Explication:
La commande sed supprime la sortie régulière à l'aide de l'
-n
option.-r
est passé pour utiliser des expressions régulières étendues, ce qui nous évite d'échapper des caractères spéciaux dans le modèle, mais ce n'est pas obligatoire.La
s
commande est utilisée pour transférer la ligne d'entrée dans la commande:Le mot clé get n'a pas indiqué la valeur. Je passe l'option
e
- qui est spécifique à GNU - à las
commande, qui dit à sed d'exécuter le résultat de la substitution en tant que commande shell et de lire ses résultats dans le tampon de modèle (même plusieurs lignes). L'utilisation de l'optionp
après (!)e
Permet d'sed
imprimer le tampon de motif après l'exécution de la commande.la source
-n
etp
, c.-à-dsed -r 's/([^ ]+) (.*)/echo "\1" \2\n/e' input
. Mais merci pour ça! Je ne connaissais pas l'e
option.e
option (introduite par GNU). Est-ce encoresed
? :)Vous pouvez essayer cette approche:
(si je comprends bien votre intention). C'est insérer "processus" au début de chaque ligne non vide pour en faire un script comme:
à évaluer (
eval
) où process est une fonction qui imprime le message attendu.la source
Si une solution non sed est acceptable, cet extrait PERL fera le travail:
la source
SEULEMENT KISS SHORT PURE SED
je vais le faire
et ça marche.
la source