Стандартний sed не може викликати оболонку ( GNU sed має розширення для цього , якщо ви дбаєте лише про вбудований Linux), тому вам доведеться виконати деяку обробку поза sed. Є кілька рішень; всі вимагають ретельного цитування.
Незрозуміло, яким саме чином потрібно розширювати значення. Наприклад, якщо рядок є
foo hello; echo $(true) 3
що з наступного має бути результатом?
k=<foo> value=<hello; echo 3>
k=<foo> value=<hello; echo 3>
k=<foo> value=<hello; echo 3>
k=<foo> value=<foo hello
3>
Я обговорю кілька варіантів нижче.
чиста оболонка
Ви можете змусити оболонку прочитати рядок введення за рядком та обробити її. Це найпростіше рішення, а також найшвидший для коротких файлів. Це найближче до вашої вимоги " echo \2":
while read -r keyword value; do
echo "k=<$keyword> v=<$(eval echo "$value")>"
done
read -r keyword valueвстановлює $keywordперше слово з обмеженим пробілом рядка та $valueрешту рядка мінус пробіл.
Якщо ви хочете розширити посилання на змінну, але не виконувати команди за межами підстановок команд, покладіть $valueвсередину документ тут . Я підозрюю, що це те, що ви справді шукали.
while read -r keyword value; do
echo "k=<$keyword> v=<$(cat <<EOF
$value
EOF
)>"
done
sed труби в оболонку
Ви можете перетворити вхідний текст у сценарій оболонки та оцінити це. Sed вирішує завдання, хоча це не так просто. Відповідаючи вашій echo \2вимозі " " (зверніть увагу, що нам потрібно уникати одиничних лапок у ключовому слові):
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
Йдучи з документом тут, нам все-таки потрібно уникати ключового слова (але інакше).
{
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
Це найшвидший метод, якщо у вас багато даних: він не запускає окремий процес для кожного рядка.
awk
Ті ж методи, які ми використовували при роботі sed з awk. Отримана програма значно читабельніша. Перехід з " echo \2":
awk '
1 {
kw = $1;
sub(/^ *[^ ]+ +/, "");
gsub(/\047/, "\047\\\047\047", $1);
print "echo \047k=<" kw ">\047 v=\\<" $0 "\\>";
}' | sh
Використання документа тут:
awk '
NR==1 { print "cat <<EOF" }
1 {
kw = $1;
sub(/^ *[^ ]+ +/, "");
gsub(/\\\$`/, "\\&", $1);
print "k=<" kw "> v=<" $0 ">";
}
END { print "EOF" }
' | sh