Bagaimana cara menghindari kutip?

65

Saya mengalami masalah dengan melarikan diri karakter dalam bash. Saya ingin menghindari tanda kutip tunggal dan ganda saat menjalankan perintah di bawah pengguna yang berbeda. Untuk keperluan pertanyaan ini, katakanlah saya ingin mengulangi yang berikut di layar:

'single quote phrase' "double quote phrase"

Bagaimana saya bisa lolos dari semua karakter khusus, jika saya juga perlu beralih ke pengguna lain:

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

Tentu saja, ini tidak membuahkan hasil yang benar.

m33lky
sumber
+1 untuk "Tentu saja, ini tidak menghasilkan hasil yang tepat". bashbaik dalam perjalanan untuk membuat saya marah.
Rolf

Jawaban:

88

Anda dapat menggunakan sintaks literal string berikut:

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

Dari man bash

Kata-kata dalam bentuk $ 'string' diperlakukan secara khusus. Kata diperluas ke string, dengan karakter backslash-escaped diganti sebagaimana ditentukan oleh standar ANSI C. Urutan melarikan diri backslash, jika ada, diterjemahkan sebagai berikut:

          \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
SiegeX
sumber
5
Berlebihan. Dalam kebanyakan kasus, Anda tidak perlu menggunakan sintaks literal string.
fpmurphy
Lebih detail di sini stackoverflow.com/a/16605140/149221
mj41
12

Dalam shell POSIX, dengan asumsi dalam string Anda tidak ada variabel, perintah atau ekspansi sejarah, dan tidak ada baris baru, ikuti resep dasar ini:

  1. Untuk mengutip string umum dengan kutipan tunggal, lakukan tindakan berikut:

    1. Ganti setiap urutan karakter non-kutipan tunggal dengan urutan yang sama dengan tanda kutip tunggal terkemuka dan tambahan: 'aaa' ==> ''aaa''

    2. Melarikan diri dengan garis miring terbalik setiap karakter kutipan tunggal yang sudah ada : ' ==> \'
      Khususnya,''aaa'' ==> \''aaa'\'

  2. Untuk mengutip string umum dengan tanda kutip ganda, lakukan tindakan berikut:

    1. Tambahkan tanda kutip ganda terkemuka dan akhir: aaa ==> "aaa"

    2. Melarikan diri dengan backslash setiap karakter kutipan ganda dan setiap karakter backslash: " ==> \", \ ==> \\

Beberapa contoh:

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

sehingga contoh Anda dapat diperluas dengan yang berikut:

#!/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\\\"\""
enzotib
sumber
10

Contoh sederhana untuk menghindari kutip di shell:

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

Ini dilakukan dengan menyelesaikan yang sudah dibuka satu ( '), menempatkan satu lolos ( \'), lalu membuka satu lagi ( ').

Kalau tidak:

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

Ini dilakukan dengan menyelesaikan yang sudah dibuka satu ( '), menempatkan kutipan di kutipan lain ( "'"), lalu membuka yang lain ( ').

Terkait: Bagaimana cara melepaskan tanda kutip tunggal dalam string tanda kutip tunggal? di stackoverflow SE

kenorb
sumber
1

Jawaban yang diterima berfungsi untuk kutipan sederhana (satu tingkat):

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

Untuk mendapatkan perintah yang disajikan untuk bekerja, Anda perlu mengutip dua kali.
Script ini bisa melakukan semua pekerjaan:

#!/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

Jalankan skrip untuk mendapatkan:

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

Baris pertama berfungsi untuk gema sederhana:

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

Baris kedua akan bekerja untuk perintah yang dikutip ganda:

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

sumber
-3

gema 'Aku siswa' tidak berfungsi. Tetapi berikut ini berfungsi:

echo $ 'I \' ma student 'Dari halaman manual bash:

Kutipan tunggal mungkin tidak terjadi di antara tanda kutip tunggal, bahkan ketika didahului oleh garis miring terbalik. .... Kata-kata dalam bentuk $ 'string' diperlakukan secara khusus. Kata diperluas ke string, dengan karakter backslash-escaped diganti sebagaimana ditentukan oleh standar ANSI C.

Sarf
sumber
6
Ini tidak menambah apa pun pada jawaban yang ada.
jasonwryan