วิธีการหลีกเลี่ยงคำพูดในเปลือก?


65

ฉันมีปัญหากับการหลบหนีตัวละครในทุบตี ฉันต้องการหลีกเลี่ยงคำพูดเดี่ยวและคู่ในขณะที่รันคำสั่งภายใต้ผู้ใช้อื่น สำหรับวัตถุประสงค์ของคำถามนี้สมมติว่าฉันต้องการที่จะสะท้อนต่อไปนี้บนหน้าจอ:

'single quote phrase' "double quote phrase"

ฉันจะหลีกเลี่ยงตัวอักษรพิเศษทั้งหมดได้อย่างไรหากฉันต้องเปลี่ยนไปใช้ผู้ใช้อื่น:

sudo su USER -c "echo \"'single quote phrase' \"double quote phrase\"\""

แน่นอนว่านี่ไม่ได้ผลลัพธ์ที่ถูกต้อง


+1 สำหรับ "แน่นอนนี่ไม่ได้ผลลัพธ์ที่ถูกต้อง" bashเป็นวิธีที่จะทำให้ฉันเป็นบ้า
Rolf

คำตอบ:


88

คุณสามารถใช้ไวยากรณ์ตัวอักษรสตริงต่อไปนี้:

> echo $'\'single quote phrase\' "double quote phrase"'
'single quote phrase' "double quote phrase"

จาก man bash

คำของฟอร์ม 'string' ได้รับการปฏิบัติเป็นพิเศษ คำนี้ขยายออกเป็นสตริงด้วยอักขระเครื่องหมายทับขวาทับกลับแทนที่ตามที่ระบุโดยมาตรฐาน ANSI C Backslash escape sequences ถ้ามีจะถูกถอดรหัสดังนี้:

          \a     alert (bell)
          \b     backspace
          \e
          \E     an escape character
          \f     form feed
          \n     new line
          \r     carriage return
          \t     horizontal tab
          \v     vertical tab
          \\     backslash
          \'     single quote
          \"     double quote
          \nnn   the eight-bit character whose value is the octal value nnn (one to three digits)
          \xHH   the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)
          \cx    a control-x character

5
overkill ในกรณีส่วนใหญ่คุณไม่จำเป็นต้องใช้ไวยากรณ์ตัวอักษร
fpmurphy

รายละเอียดเพิ่มเติมได้ที่นี่stackoverflow.com/a/16605140/149221
mj41

12

ใน POSIX เชลล์สมมติว่าสตริงของคุณไม่มีตัวแปรคำสั่งหรือการขยายประวัติและไม่มีการขึ้นบรรทัดใหม่ให้ทำตามคำสั่งพื้นฐานเหล่านี้:

  1. ในการอ้างอิงสตริงทั่วไปด้วยอัญประกาศเดี่ยวให้ดำเนินการต่อไปนี้:

    1. แทนลำดับของอักขระที่ไม่ใช่เครื่องหมายคำพูดเดี่ยวใด ๆ ด้วยลำดับเดียวกันด้วยเครื่องหมายคำพูดเดี่ยวชั้นนำและต่อท้ายที่เพิ่มเข้ามา: 'aaa' ==> ''aaa''

    2. หลบหนีด้วยแบ็กสแลชทุกตัวละครที่อ้างถึงมาก่อน : ' ==> \'
      โดยเฉพาะ''aaa'' ==> \''aaa'\'

  2. ในการอ้างอิงสตริงทั่วไปด้วยเครื่องหมายคำพูดคู่ให้ดำเนินการดังต่อไปนี้:

    1. เพิ่มคำพูดสองชั้นนำและต่อท้าย: aaa ==> "aaa"

    2. หลบหนีด้วยแบ็กสแลชทุกอักขระเครื่องหมายคำพูดคู่และอักขระแบ็กสแลชทุกตัว: " ==> \", \ ==> \\

ตัวอย่างสองตัวอย่าง:

''aaa""bbb''ccc\\ddd''  ==>  \'\''aaa""bbb'\'\''ccc\\ddd'\'\'
                        ==>  "''aaa\"\"bbb''ccc\\\\ddd''"

เพื่อให้ตัวอย่างของคุณสามารถขยายได้ดังต่อไปนี้:

#!/bin/sh

echo \''aaa'\'' "bbb"'
echo "'aaa' \"bbb\""

sudo su enzotib -c 'echo \'\'\''aaa'\''\'\'\'' "bbb"'\'
sudo su enzotib -c 'echo "'\''aaa'\'' \"bbb\""'

sudo su enzotib -c "echo \\''aaa'\\'' \"bbb\"'"
sudo su enzotib -c "echo \"'aaa' \\\"bbb\\\"\""

10

ตัวอย่างง่ายๆของการหลีกเลี่ยงคำพูดในเชลล์:

$ echo 'abc'\''abc'
abc'abc
$ echo "abc"\""abc"
abc"abc

มันทำโดยการเปิดแล้วเสร็จหนึ่ง ( ') วางหนีหนึ่ง ( \') แล้วเปิดอีกหนึ่ง ( ')

อีกวิธีหนึ่งคือ:

$ echo 'abc'"'"'abc'
abc'abc
$ echo "abc"'"'"abc"
abc"abc

มันเสร็จสิ้นโดยเปิดแล้วหนึ่ง ( ') วางใบเสนอราคาในใบเสนอราคาอื่น ( "'") แล้วเปิดอีกหนึ่ง ( ')

ที่เกี่ยวข้อง: วิธีการหลีกเลี่ยงคำพูดเดี่ยวภายในสตริงที่ยกมาเดี่ยว? ที่ stackoverflow SE


1

คำตอบที่ได้รับการยอมรับนั้นใช้สำหรับการอ้างอิงแบบง่าย ๆ (หนึ่งระดับ):

$ echo $'\'single quote phrase\' "double quote phrase"'
'single quote phrase' "double quote phrase"

หากต้องการรับคำสั่งที่นำเสนอให้ทำงานคุณต้องพูดสองครั้ง
สคริปต์นี้สามารถทำงานได้ทั้งหมด:

#!/bin/bash

quote () { 
    local quoted=${1//\'/\'\\\'\'};
    printf "'%s'" "$quoted"
}

read -r line <<-\_line_to_quote_
'single quote phrase' "double quote phrase"
_line_to_quote_

quote "$line"; echo
quote "echo $(quote "$line")"; echo

เรียกใช้งานสคริปต์เพื่อรับ:

$ script
''\''single quote phrase'\'' "double quote phrase"'
'echo '\'''\''\'\'''\''single quote phrase'\''\'\'''\'' "double quote phrase"'\'''

บรรทัดแรกใช้ได้กับเสียงสะท้อนที่เรียบง่าย:

$ echo ''\''single quote phrase'\'' "double quote phrase"'
'single quote phrase' "double quote phrase"

บรรทัดที่สองจะทำงานสำหรับคำสั่งที่ยกมาสองครั้ง:

sudo su USER -c 'echo '\'''\''\'\'''\''single quote phrase'\''\'\'''\'' "double quote phrase"'\'''

-3

echo 'I \' นักเรียน 'ไม่ทำงาน แต่งานดังต่อไปนี้:

echo $ 'I \' นักเรียน 'จากหน้าคนทุบตี:

เครื่องหมายคำพูดเดี่ยวอาจไม่เกิดขึ้นระหว่างเครื่องหมายคำพูดเดี่ยวแม้ว่าจะนำหน้าด้วยเครื่องหมายทับขวา .... คำศัพท์ในแบบฟอร์ม 'string' ได้รับการปฏิบัติเป็นพิเศษ คำนี้ขยายออกเป็นสตริงด้วยอักขระเครื่องหมายทับขวาทับกลับแทนที่ตามที่ระบุโดยมาตรฐาน ANSI C


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