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
foo hello; echo $(true) 3
lequel des éléments suivants devrait être la sortie?
k=<foo> value=<hello; echo 3>
k=<foo> value=<hello; echo 3>
k=<foo> value=<hello; echo 3>
k=<foo> value=<foo hello
3>
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
":
while read -r keyword value; do
echo "k=<$keyword> v=<$(eval echo "$value")>"
done
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.
while read -r keyword value; do
echo "k=<$keyword> v=<$(cat <<EOF
$value
EOF
)>"
done
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é):
sed -e 's/^ *//' -e 'h' \
-e 's/[^ ]* *//' -e 'x' \
-e 's/ .*//' -e "s/'/'\\\\''/g" -e "s/^/echo 'k=</" \
-e 'G' -e "s/\n/>' v=\\</" -e 's/$/\\>/' | sh
Pour aller avec un document ici, nous devons toujours échapper au mot-clé (mais différemment).
{
echo 'cat <<EOF'
sed -e 's/^ */k=</' -e 'h' \
-e 's/[^ ]* *//' -e 'x' -e 's/ .*//' -e 's/[\$`]/\\&/g' \
-e 'G' -e "s/\n/> v=</" -e 's/$/>/'
echo 'EOF'
} | sh
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
":
awk '
1 {
kw = $1;
sub(/^ *[^ ]+ +/, "");
gsub(/\047/, "\047\\\047\047", $1);
print "echo \047k=<" kw ">\047 v=\\<" $0 "\\>";
}' | sh
Utilisation d'un document ici:
awk '
NR==1 { print "cat <<EOF" }
1 {
kw = $1;
sub(/^ *[^ ]+ +/, "");
gsub(/\\\$`/, "\\&", $1);
print "k=<" kw "> v=<" $0 ">";
}
END { print "EOF" }
' | sh