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 archvà arch2và 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 archvà arch2và 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, grepsẽ trả về các loại giá trị:
"arch"
"arch2"
Các đường ống sedsẽ 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 sedthự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/glà 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 trcó 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 greptí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 sednhư sed '/^"\(arch[^"]*\)/s//\1/bạn sẽ chỉ hoạt động trên các dòng có chứa chuỗi đó.
sedthự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
cutchia 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 sedbạ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 bashbạ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-regexptù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. (trthông thường sẽ dịch một bộ ký tự thành một ký tự khác;-dbảo nó chỉ xóa chúng đi.)