Sed tiêu chuẩn không thể gọi shell ( GNU sed có phần mở rộng để làm điều đó , nếu bạn chỉ quan tâm đến Linux không nhúng), vì vậy bạn sẽ phải thực hiện một số xử lý bên ngoài sed. Có một số giải pháp; tất cả yêu cầu trích dẫn cẩn thận.
Không rõ chính xác bạn muốn các giá trị được mở rộng như thế nào. Ví dụ: nếu một dòng là
foo hello; echo $(true) 3
cái nào sau đây nên là đầu ra?
k=<foo> value=<hello; echo 3>
k=<foo> value=<hello; echo 3>
k=<foo> value=<hello; echo 3>
k=<foo> value=<foo hello
3>
Tôi sẽ thảo luận về một số khả năng dưới đây.
vỏ nguyên chất
Bạn có thể lấy shell để đọc dòng đầu vào theo dòng và xử lý nó. Đây là giải pháp đơn giản nhất và cũng nhanh nhất cho các tệp ngắn. Đây là điều gần nhất với yêu cầu của bạn echo \2
.
while read -r keyword value; do
echo "k=<$keyword> v=<$(eval echo "$value")>"
done
read -r keyword value
đặt $keyword
thành từ được phân tách bằng khoảng trắng đầu tiên của dòng và $value
phần còn lại của dòng trừ khoảng trắng theo sau.
Nếu bạn muốn mở rộng các tham chiếu biến, nhưng không thực hiện các lệnh bên ngoài thay thế lệnh, hãy đặt $value
bên trong một tài liệu ở đây . Tôi nghi ngờ rằng đây là những gì bạn đang thực sự tìm kiếm.
while read -r keyword value; do
echo "k=<$keyword> v=<$(cat <<EOF
$value
EOF
)>"
done
sed đường ống vào một vỏ
Bạn có thể chuyển đổi đầu vào thành một kịch bản shell và đánh giá điều đó. Sed là nhiệm vụ, mặc dù nó không phải là dễ dàng. Thực hiện theo echo \2
yêu cầu của bạn (ghi chú rằng chúng tôi cần thoát các trích dẫn đơn trong từ khóa):
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
Đi với một tài liệu ở đây, chúng ta vẫn cần phải thoát khỏi từ khóa (nhưng khác nhau).
{
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
Đây là phương pháp nhanh nhất nếu bạn có nhiều dữ liệu: nó không bắt đầu một quy trình riêng cho mỗi dòng.
ôi
Các kỹ thuật tương tự chúng tôi đã sử dụng với sed làm việc với awk. Chương trình kết quả là dễ đọc hơn đáng kể. Đi với đỉnh điểm echo \2
:
awk '
1 {
kw = $1;
sub(/^ *[^ ]+ +/, "");
gsub(/\047/, "\047\\\047\047", $1);
print "echo \047k=<" kw ">\047 v=\\<" $0 "\\>";
}' | sh
Sử dụng tài liệu ở đây:
awk '
NR==1 { print "cat <<EOF" }
1 {
kw = $1;
sub(/^ *[^ ]+ +/, "");
gsub(/\\\$`/, "\\&", $1);
print "k=<" kw "> v=<" $0 ">";
}
END { print "EOF" }
' | sh