Tôi có đầu ra từ VBoxManage list vms
đó trông như thế này:
"arch" {de1a1db2-86c5-43e7-a8de-a0031835f7a7}
"arch2" {92d8513c-f13e-41b5-97e2-2a6b17d47b67}
Tôi cần phải lấy tên arch
và arch2
và lưu chúng vào một biến.
Tôi có đầu ra từ VBoxManage list vms
đó trông như thế này:
"arch" {de1a1db2-86c5-43e7-a8de-a0031835f7a7}
"arch2" {92d8513c-f13e-41b5-97e2-2a6b17d47b67}
Tôi cần phải lấy tên arch
và arch2
và lưu chúng vào một biến.
Câu trả lời:
Điều này sẽ phân tích nội dung của 2 chuỗi đó:
$ grep -o '".*"' somefile | sed 's/"//g'
arch
arch2
Ở trên tìm kiếm một chuỗi phù hợp với mô hình ".*"
. Điều đó sẽ phù hợp với bất cứ điều gì xảy ra trong dấu ngoặc kép. Vì vậy, grep
sẽ trả về các loại giá trị:
"arch"
"arch2"
Các đường ống sed
sẽ loại bỏ bất kỳ dấu ngoặc kép nào từ các chuỗi này cung cấp cho các chuỗi bạn đang tìm kiếm. Ký hiệu sed 's/"//g'
này đang hướng dẫn sed
thực hiện tìm kiếm và thay thế trên tất cả các lần xuất hiện của dấu ngoặc kép, thay thế chúng bằng không có gì , s/"//g
. Lệnh s/find/replace/g
là những gì đang diễn ra ở đó, và dấu vết g
để tìm kiếm bảo nó thực hiện nó trên toàn cầu trên toàn bộ chuỗi mà nó đưa ra.
Bạn cũng có thể sử dụng sed
để cắt bỏ trích dẫn kép bắt đầu, giữ những gì ở giữa chúng và cắt bỏ phần trích dẫn còn lại + mọi thứ ở đó sau:
$ sed 's/^"\(.*\)".*/\1/' a
arch
arch2
$ grep -o '".*"' somefile | tr -d '"'
arch
arch2
Lệnh tr
có thể được sử dụng để xóa các ký tự. Trong trường hợp này, nó sẽ xóa dấu ngoặc kép.
$ grep -oP '(?<=").*(?=")' somefile
arch
arch2
Sử dụng grep
tính năng PCRE của bạn, bạn có thể tìm kiếm bất kỳ chuỗi con nào bắt đầu bằng dấu ngoặc kép hoặc kết thúc bằng dấu ngoặc kép và chỉ báo cáo chuỗi con.
/address/
đến sed
như sed '/^"\(arch[^"]*\)/s//\1/
bạn sẽ chỉ hoạt động trên các dòng có chứa chuỗi đó.
sed
thực sự nên làm s/^"\([^"]*\)".*/\1/
trong trường hợp không chỉ có hai dấu ngoặc kép trên dòng.
Đó là một công việc khác cho cut
:
VBoxManage list vms | cut -d \" -f2
cut
chia từng dòng thành các trường bằng cách sử dụng dấu ngoặc kép làm dấu phân cách, sau đó xuất trường 2: trường 1 là chuỗi trống trước trích dẫn đầu tiên, trường 2 là chuỗi mong muốn giữa các dấu ngoặc kép và trường 3 là phần còn lại của hàng.
Với sed
bạn có thể làm:
var=$(VBoxManage list vms | sed 's/^"\([^"]*\).*/\1/')
Giải trình:
s/.../.../
- phù hợp và thay thế^
- trận đấu ở đầu dòng\(...\)
- đây là một tài liệu tham khảo trở lại, chúng ta có thể tham khảo những gì phù hợp ở đây sau với \1
[^"]*
- khớp với bất kỳ chuỗi nào không chứa "
(tức là đến chuỗi tiếp theo "
).*
- phù hợp với phần còn lại của dòng\1
- thay thế bằng tham chiếu trở lạiHoặc với awk
:
var=$(VBoxManage list vms | awk -F\" '{ print $2 }')
Lưu ý rằng trong shell hiện đại, bạn cũng có thể sử dụng một mảng thay vì một biến thông thường. Trong bash
bạn có thể làm:
IFS=$'\n'; set -f
array=( $(VBoxManage list vms | awk -F\" '{ print $2 }') )
echo "array[0] = ${array[0]}"
echo "array[1] = ${array[1]}"
Điều này có thể dễ dàng hơn khi bạn sử dụng biến.
Sử dụng bash, tôi sẽ viết:
while read vm value; do
case $vm in
'"arch"') arch=$value ;;
'"arch2"') arch2=$value ;;
esac
done < <( VBoxManage list vms )
echo $arch
echo $arch2
Và một thông qua grep oneliner với --perl-regexp
tùy chọn,
VBoxManage list vms | grep -oP '(?<=^\")[^"]*'
Giải trình:
(?<=^\")[^"]*
-> Một cái nhìn được sử dụng ở đây. Nó phù hợp với bất kỳ nhân vật nào nhưng không phải của"
bằng 0 hoặc nhiều lần (một khi tìm thấy dấu ngoặc kép, nó dừng khớp) chỉ sau dấu ngoặc kép (chỉ dòng bắt đầu bằng dấu ngoặc kép).
Một hack xấu xí khác sed
,
$ sed '/.*\"\(.*\)\".*/ s//\1/g' file
arch
arch2
vì regex có chế độ tham lam và không tham lam, nếu bạn có nhiều mục tiêu trên cùng một dòng, nó sẽ không trích xuất như bạn muốn. Hàng:
"tom" is a cat, and "jerry" is a mouse.
Mục tiêu:
tom
jerry
Lệnh (chế độ tham lam):
grep -oP '".*"' name
Lệnh (chế độ không tham lam):
grep -oP '".*?"' name
tr -d \"
là một cách khác để xóa dấu ngoặc kép. (tr
thông thường sẽ dịch một bộ ký tự thành một ký tự khác;-d
bảo nó chỉ xóa chúng đi.)