วิธีหลีกหนีคำพูดเดียวภายใน awk


111

ฉันต้องการทำสิ่งต่อไปนี้

awk 'BEGIN {FS=" ";} {printf "'%s' ", $1}'

แต่การหลีกเลี่ยงคำพูดเดี่ยวด้วยวิธีนี้ไม่ได้ผล

awk 'BEGIN {FS=" ";} {printf "\'%s\' ", $1}'

ต้องทำอย่างไร? ขอบคุณที่ช่วยเหลือ.


มีหลายภาษาที่จะหลีกเลี่ยงเครื่องหมายคำพูดโดยใส่สองภาษาในแถวเดียวกันอาจลองทำเช่นนั้น
joshuahealy

ฉันลอง awk 'BEGIN {FS = "";} {printf "' '% s' '", $ 1}' แต่ไม่มีการพิมพ์ใบเสนอราคา

หน้านี้ระบุว่าการรวมเครื่องหมายคำพูดเดียวในสตริงที่มีเครื่องหมายอัญประกาศเดี่ยวเป็นไปไม่ได้ บางทีคุณอาจต้องแปลงเป็นเครื่องหมายคำพูดคู่
joshuahealy

2
เป็นไปไม่ได้ แต่สตริงเปลือกเดี่ยวสองอันที่อยู่ติดกันจะกาวเข้าด้วยกันเป็นพารามิเตอร์เดียว และสตริงเชลล์ที่ยกมาตัวเดียวสองตัวที่ติดกาวด้วยอักขระที่ไม่ใช่ช่องว่างยังรวมอยู่ในลูกโลกขนาดใหญ่หนึ่งอัน'abc'd'ef'นั่นคือabcdef: ลิเทอรัลบวกdบวกลิเทอรัล dอยู่นอกคำพูดและคุณสามารถแทนที่dด้วย\'เพื่อให้ที่ประเมิน'abc'\''ef' abc'ef
Kaz

คำตอบ:


160

นี่อาจเป็นสิ่งที่คุณกำลังมองหา:

awk 'BEGIN {FS=" ";} {printf "'\''%s'\'' ", $1}'

นั่นคือเมื่อ'\''คุณปิดช่องเปิด'จากนั้นพิมพ์ลิเทอรัล'โดยการหลบหนีจากนั้นเปิด'อีกครั้งในที่สุด


48
มันไม่มีส่วนเกี่ยวข้องกับ awk 'ตัวละครปิดเปิด'สตริงเปลือกตัวอักษร ลิเทอรัลของเชลล์ไม่สนับสนุนการหลีกเลี่ยงแบ็กสแลชสำหรับสิ่งนี้ ลำดับ'\''ไม่หลอกลวง: มันปิดอ้างเดียวตัวอักษรระบุตัวอักษรคำพูด (โดยใช้การหลบหนีที่จะได้รับการสนับสนุนด้านนอกของตัวอักษรอ้างเดียว) และ re-เปิดใหม่อ้างเดียวที่แท้จริง คุณสามารถคิดว่ามันเป็นลำดับการหลีกเลี่ยงสี่อักขระเพื่อให้ได้ใบเสนอราคาเดียว :)
Kaz

2
@ สตีฟ: ขอบคุณมากสำหรับคำตอบที่เป็นประโยชน์ของคุณ คุณช่วยฉันปวดหัวมาก!
John Slegers

4
@syntaxerror อัญประกาศที่คุณใช้ในการเตรียมอาร์กิวเมนต์สำหรับการเรียกใช้awkเป็นเพียงเรื่องของตัวแปลคำสั่งที่คุณใช้ในการเขียนบรรทัดคำสั่ง การ'{printf $2}'ทำให้กลายเป็นอาร์กิวเมนต์สำหรับการexecveเรียกระบบหรือสิ่งที่คล้ายกันซึ่งดูเหมือนสตริง C ที่สิ้นสุดด้วยค่าว่างโดยไม่มีเครื่องหมายคำพูดใด ๆ Awk ไม่เคยเห็นคำพูดและไม่ชอบ คุณสามารถในการใช้งานจริงราคาสองครั้ง แต่ราคาคู่ไม่ป้องกันการขยายตัวของเปลือกของ$2คุณจึงต้องหลบหนีเครื่องหมายดอลลาร์ด้วย backslash "{printf \$2}"ที่จะทำให้มันตัวอักษร:
Kaz

4
@syntaxerror ตามกำหนดเองสคริปต์ awk ในบรรทัดมักจะใช้เครื่องหมายคำพูดเดี่ยวเนื่องจากไวยากรณ์ awk มักมีองค์ประกอบคำศัพท์ที่พิเศษสำหรับเชลล์เช่นลิเทอรัลสตริงที่ยกมาสองครั้งและฟิลด์ที่มีตัวเลขแสดงด้วยเครื่องหมายดอลลาร์ หากนิพจน์ทั่วไป sed (หรืออะไรก็ตาม) มีไวยากรณ์ของเชลล์คุณต้องระวังด้วย sed -e "s/$FOO/$BAR/"จะไม่ทำงานถ้าเจตนาคือการแทนที่ข้อความตัวอักษรด้วย$FOO $BARวิธีที่ง่ายที่สุดก็sed -e 's/$FOO/$BAR/คือ
Kaz

1
@syntaxerror หากคุณใส่โปรแกรม awk ไว้ในเครื่องหมายอัญประกาศคู่คุณจะพบกับการ Escape มากมายเช่นawk "{ print \"abc\", \$1 }". เมื่อใดก็ตามที่อัญประกาศปรากฏขึ้นในโปรแกรม awk จะต้องมีการ Escape เพื่อไม่ให้ปิดใบเสนอราคาเชลล์ และเปรียบเทียบสิ่งนี้: awk '{print "\\"}'(พิมพ์แบ็กสแลช) กับสิ่งที่ต้องใช้กับเครื่องหมายคำพูดคู่: awk "BEGIN {print \"\\\\\" }", ฟิ้ว! เครื่องหมายคำพูดทั้งสองต้องมีการหลีกเลี่ยงและแบ็กสแลชทั้งสอง เปลือกแปรรูป\\ ไป\ ดังนั้นเราจึงจำเป็นที่จะเข้ารหัส\\\\ \\
Kaz

76

ใบเสนอราคาเดียวจะแสดงโดยใช้ \x27

ชอบใน

awk 'BEGIN {FS=" ";} {printf "\x27%s\x27 ", $1}'

ที่มา


16
+1 แต่ต้องเพิ่ม: \x27เป็นส่วนขยาย; POSIX Awk \047เพียงตระหนัก ( \47ก็ใช้ได้เช่นกันถ้าไม่ตามด้วยเลขฐานแปด)
hemflit

1
คุณจะจบ \ x27 ได้อย่างไรถ้าคุณมีตัวเลขอื่นตามมา
Jason Axelson

1
Jason คุณต่อตัวอักษรสองสตริงเข้าด้วยกัน: "AAA \ x27" "1" หรือคุณแค่ใช้เลขฐานแปด
hemflit

9
มักจะใช้ฐานแปด ( \047) ไม่ใช่ฐานสิบหก ( \x27) หลบหนีรหัส - ดูawk.freeshell.org/PrintASingleQuote
Ed Morton

35

อีกทางเลือกหนึ่งคือการส่งใบเสนอราคาเดียวเป็นตัวแปร awk :

awk -v q=\' 'BEGIN {FS=" ";} {printf "%s%s%s ", q, $1, q}'

ตัวอย่างที่ง่ายกว่าด้วยการต่อสายอักขระ:

# Prints 'test me', *including* the single quotes.
$ awk -v q=\' '{print q $0 q }' <<<'test me'
'test me'

5
สิ่งนี้ชัดเจนและกระชับโดยเฉพาะอย่างยิ่งหากคุณต้องใช้เครื่องหมายคำพูดจำนวนมาก
Peter Gluck

18
awk 'BEGIN {FS=" "} {printf "\047%s\047 ", $1}'

1
ตราบใดที่ฉันจำได้ว่า\047เป็นลำดับเลขฐานแปดสำหรับอักขระอัญประกาศเดี่ยวฉันพบว่าทางเลือกนี้อ่านได้ง่ายที่สุด
Anthony Geoghegan

4

สำหรับสคริปต์ขนาดเล็กวิธีที่เป็นทางเลือกในการทำให้อ่านได้คือการใช้ตัวแปรเช่นนี้:

awk -v fmt="'%s'\n" '{printf fmt, $1}'

ฉันพบว่ามันเป็น Conveninet ในกรณีที่ฉันต้องสร้างอักขระอัญประกาศเดี่ยวหลายครั้งในเอาต์พุตและ \ 047 ทำให้ไม่สามารถอ่านได้ทั้งหมด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.