ฉันมีผลลัพธ์จากVBoxManage list vmsที่มีลักษณะเช่นนี้:
"arch" {de1a1db2-86c5-43e7-a8de-a0031835f7a7}   
"arch2" {92d8513c-f13e-41b5-97e2-2a6b17d47b67}  
ฉันต้องการที่จะคว้าชื่อarchและarch2และบันทึกไว้ในตัวแปร  
ฉันมีผลลัพธ์จากVBoxManage list vmsที่มีลักษณะเช่นนี้:
"arch" {de1a1db2-86c5-43e7-a8de-a0031835f7a7}   
"arch2" {92d8513c-f13e-41b5-97e2-2a6b17d47b67}  
ฉันต้องการที่จะคว้าชื่อarchและarch2และบันทึกไว้ในตัวแปร  
คำตอบ:
นี่จะแยกเนื้อหาของ 2 สายเหล่านี้:
$ grep -o '".*"' somefile | sed 's/"//g'
arch
arch2
".*"ลักษณะดังกล่าวข้างต้นเป็นข้อความที่ตรงกับรูปแบบ ที่จะตรงกับสิ่งที่เกิดขึ้นภายในเครื่องหมายคำพูดคู่ ดังนั้นgrepจะส่งคืนค่าประเภทเหล่านี้:
"arch"
"arch2"
ไปป์ที่sedจะตัดเครื่องหมายคำพูดคู่ใด ๆ จากสตริงเหล่านี้ให้สตริงที่คุณต้องการ สัญกรณ์sed 's/"//g'จะสอนจะค้นหาและแทนที่ในเหตุการณ์ที่เกิดขึ้นทั้งหมดของคำพูดคู่แทนพวกเขาด้วยอะไรsed s/"//gคำสั่งs/find/replace/gคือสิ่งที่เกิดขึ้นที่นั่นและการติดตามgเพื่อค้นหาบอกให้ทำแบบโกลบอลบนสตริงทั้งหมดที่ได้รับ
คุณยังสามารถใช้sedเพื่อตัดเครื่องหมายอัญประกาศเริ่มต้นเก็บสิ่งที่อยู่ระหว่างพวกเขาและตัดเครื่องหมายอัญประกาศที่เหลือ + ทุกอย่างที่มีหลังจาก:
$ sed 's/^"\(.*\)".*/\1/' a
arch
arch2
$ grep -o '".*"' somefile | tr -d '"'
arch
arch2
trสามารถใช้คำสั่งเพื่อลบอักขระได้ ในกรณีนี้มันเป็นการลบเครื่องหมายคำพูดคู่
$ grep -oP '(?<=").*(?=")' somefile
arch
arch2
การใช้grepคุณสมบัติ PCRE ของคุณสามารถค้นหาสตริงย่อยใด ๆ ที่เริ่มต้นด้วยเครื่องหมายคำพูดคู่หรือลงท้ายด้วยเครื่องหมายคำพูดคู่และรายงานเพียงสตริงย่อย
/address/ที่sedชอบsed '/^"\(arch[^"]*\)/s//\1/คุณจะทำงานในบรรทัดที่มีสตริงนั้นเท่านั้น
                    sedควรจะทำจริงๆs/^"\([^"]*\)".*/\1/ในกรณีที่มีเพียงสองเครื่องหมายคำพูดในบรรทัด
                    นั่นเป็นงานอีกอย่างสำหรับcut:
VBoxManage list vms | cut -d \" -f2
cutแบ่งแต่ละบรรทัดออกเป็นฟิลด์โดยใช้เครื่องหมายคำพูดเป็นตัวคั่นจากนั้นฟิลด์เอาท์พุต 2: ฟิลด์ 1 คือสตริงว่างก่อนอัญประกาศแรกฟิลด์ 2 เป็นสตริงที่ต้องการระหว่างเครื่องหมายคำพูดและฟิลด์ 3 เป็นส่วนที่เหลือของ เส้น
                    ด้วยsedคุณสามารถทำ:
var=$(VBoxManage list vms | sed 's/^"\([^"]*\).*/\1/')
คำอธิบาย:
s/.../.../ - จับคู่และแทนที่^- การแข่งขันที่จุดเริ่มต้นของบรรทัด\(...\) - นี่คือการอ้างอิงย้อนกลับเราสามารถอ้างถึงสิ่งที่ตรงกับที่นี่ในภายหลังด้วย \1[^"]*- จับคู่ลำดับใด ๆ ที่ไม่มี"(เช่นจนถึงลำดับถัดไป").* - จับคู่ส่วนที่เหลือของบรรทัด\1 - แทนที่ด้วยการอ้างอิงด้านหลังหรือด้วยawk:
var=$(VBoxManage list vms | awk -F\" '{ print $2 }')
โปรดทราบว่าในเชลล์ที่ทันสมัยคุณสามารถใช้อาร์เรย์แทนตัวแปรปกติได้ ในbashสิ่งที่คุณสามารถทำได้:
IFS=$'\n'; set -f
array=( $(VBoxManage list vms | awk -F\" '{ print $2 }') )
echo "array[0] = ${array[0]}"
echo "array[1] = ${array[1]}"
นี่อาจจะง่ายขึ้นเมื่อคุณใช้ตัวแปร
ใช้ทุบตีฉันจะเขียน:
while read vm value; do
    case $vm in
        '"arch"') arch=$value ;;
        '"arch2"') arch2=$value ;;
    esac
done < <( VBoxManage list vms )
echo $arch
echo $arch2
และหนึ่งผ่าน grep oneliner พร้อม--perl-regexpตัวเลือก
VBoxManage list vms | grep -oP '(?<=^\")[^"]*'
คำอธิบาย:
(?<=^\")[^"]*-> Lookbehind ใช้ที่นี่ มันตรงกับตัวละครใด ๆ แต่ไม่"เป็นศูนย์หรือมากกว่าครั้ง (เมื่อพบคำพูดสองครั้งก็หยุดการจับคู่) ซึ่งเป็นเพียงหลังเครื่องหมายคำพูดคู่ (เฉพาะบรรทัดที่เริ่มต้นด้วยคำพูดคู่)
อื่นผ่านสับน่าเกลียดsed,
$ sed '/.*\"\(.*\)\".*/ s//\1/g' file
arch
arch2
เนื่องจาก regex มีโหมดโลภและไม่โลภหากคุณมีเป้าหมายหลายรายการในบรรทัดเดียวกันมันจะไม่แยกตามที่คุณต้องการ เส้น:
"tom" is a cat, and "jerry" is a mouse. 
เป้าหมาย:
tom
jerry
คำสั่ง (โหมดโลภ):
grep -oP '".*"' name
คำสั่ง (โหมดที่ไม่ใช่โลภ):
grep -oP '".*?"' name
tr -d \"เป็นอีกวิธีในการลบเครื่องหมายคำพูด (trโดยปกติจะแปลอักขระหนึ่งชุดเป็นอีกชุดหนึ่ง-dให้บอกให้ลบทิ้งแทน)