Bagaimana cara menggunakan karakter khusus seperti yang normal?

13

Banyak pertanyaan seperti 'Cara mengetik char tanda kutip ganda (")?' sedang ditanyakan, dan kami tidak ingin mengacaukan komunitas kami dengan jawaban yang sama (Ketik seolah- \"olah tidak dilampirkan dalam ', "jika terlampir dalam '.) Jadi, pertanyaannya ada di sini.

Anda tidak dapat mengetik karakter khusus ke terminal seperti yang normal, mis. Perintah ini akan gagal:

echo Updates (11)

Jadi, bagaimana cara mengetik karakter ini di terminal seolah-olah itu yang normal?

!#$^&*?[](){}<>~;'"\|<space><tab><newline>
EKons
sumber
Tidak ada shell Unix yang saya tahu di mana carriage-return adalah spesial. =, @dan %spesial di beberapa shell dalam beberapa konteks.
Stéphane Chazelas
@ StéphaneChazelas Umm ... carriage return ( ^M) bertindak seperti umpan baris ( ^J) kepada saya (Ubuntu 14,04, sh).
EKons
Tidak, driver terminal Anda berubah ^Mmenjadi ^Jpada input tetapi ^Mtidak khusus untuk shell dan tidak perlu dikutip. Ketik echo ^V^M | hddan Anda akan melihat karakter 0d (dan 0a ditambahkan oleh gema).
Stéphane Chazelas
@ StéphaneChazelas Umm ... Saya tidak tahu apa hditu, mungkin xxdlebih baik sebagai penampil hex.
EKons
Mana saja. Gunakan POSIX od -tx1atau sed -n latau vim's xxd jika Anda tidak punya hd. Beberapa sistem juga memiliki cat -vteataucat -A
Stéphane Chazelas

Jawaban:

26

Itu sangat tergantung pada shell. Periksa manual shell Anda untuk detailnya.

Perhatikan juga bahwa beberapa karakter hanya spesial dalam beberapa konteks. Misalnya, di sebagian besar shell, *dan ?hanya khusus dalam konteks daftar, di POSIX atau shell seperti csh, ~hanya spesial di awal kata atau mengikuti beberapa karakter seperti :. Sama untuk =di zsh. Dalam beberapa shell, [hanya khusus ketika dicocokkan (dengan beberapa batasan) oleh a ].

Dalam beberapa shell seperti bashatau yash, karakter khusus seperti pembatas token kosong juga bervariasi dengan lokal.

Operator mengutip (untuk menghapus arti khusus dari karakter-karakter itu) juga sangat bervariasi antar shell.

Kerang mirip Bourne

Ringkasan untuk cangkang mirip Bourne (yaitu cangkang yang telah dikenal dipanggil shpada beberapa sistem atau lainnya sejak tahun 80-an):

Shell Bourne

Karakter spesial:

  • "\'&|;()^`<>$, spasi, baris baru dan tab khusus dalam baris perintah sederhana saat tidak dikutip.
  • #(kecuali dalam versi awal) adalah khusus di awal baris atau mengikuti spasi, tanda kutip atau &|()^<>;`.
  • {dan }hanya istimewa karena merupakan kata kunci shell (jadi hanya kata-kata di posisi perintah).
  • *?[khusus sebagai operator globbing, jadi hanya dalam konteks daftar. Dalam kasus [, itu [...]adalah operator globbing, baik [atau ]hanya perlu dikutip untuk menghilangkan makna khusus.
  • =khusus ketika dalam konteks di mana ia diperlakukan sebagai operator penugasan. Artinya, dalam perintah sederhana, untuk semua kata yang tidak mengikuti argumen (kecuali setelah set -k).

Mengutip operator

  • \mengutip semua karakter khusus kecuali baris baru ( \<newline>adalah cara untuk melanjutkan garis logis panjang ke baris fisik berikutnya , sehingga urutan dihapus). Perhatikan bahwa backtick menambah kompleksitas tambahan seperti di dalamnya, \digunakan terlebih dahulu untuk menghindari backtick penutup dan membantu pengurai. Di dalam tanda kutip ganda, \hanya dapat digunakan untuk melarikan diri ",, $dan `( \<newline>masih merupakan garis-kelanjutan). Di dalam dokumen di sini, sama kecuali untuk ". \adalah satu-satunya cara untuk melarikan diri karakter dalam dokumen di sini.
  • "..."tanda kutip ganda lolos dari semua karakter kecuali dirinya sendiri \,, $dan `.
  • '...' Kutipan tunggal lolos dari semua karakter kecuali dirinya sendiri.

Kerang POSIX

Cangkang POSIX sebagian besar berperilaku seperti cangkang Bourne, kecuali bahwa:

ksh

seperti POSIX kecuali itu:

  • {string}khusus jika string berisi tanda kutip ,(atau ..dalam beberapa kasus dan dengan beberapa versi).
  • ksh93 memiliki operator kutipan khusus tambahan: $'...'dengan aturan yang rumit. Operator yang juga ditemukan (dengan beberapa variasi) di bash, zsh, mkshdan FreeBSD dan busybox sh.
  • ksh93juga memiliki $"..."operator kutipan yang berfungsi seperti "..."kecuali bahwa string tunduk pada pelokalan (dapat dikonfigurasi sehingga diterjemahkan ke bahasa pengguna). mkshmengabaikan $in $"...".

bash

suka ksh93tapi:

  • dalam karakter lokal byte tunggal, semua karakter kosong (sesuai dengan lokal) dianggap sebagai pembatas (seperti spasi atau tab). Akibatnya, itu berarti Anda harus mengutip semua byte dengan bit ke-8 yang diatur jika mereka mungkin karakter kosong di beberapa lokal.
  • Ketika ekspansi sejarah csh diaktifkan seperti dalam contoh interaktif, !khusus dalam beberapa konteks dan tanda kutip ganda tidak selalu menghindarinya. Dan ^spesial di awal perintah.

zsh

suka ksh93tapi:

  • catatan yang sama seperti untuk bashekspansi sejarah csh
  • =khusus sebagai karakter pertama dari sebuah kata ( =lsdiperluas ke /bin/ls).
  • {dan }juga dapat membuka dan menutup grup perintah ketika tidak dibatasi (seperti pada {echo text}karya seperti Bourne { echo text;}).
  • kecuali untuk [sendiri, [kebutuhan dikutip bahkan jika tidak ditutup dengan ].
  • Dengan extendedglobopsi diaktifkan #,, ^dan ~merupakan operator globbing.
  • Dengan bracecclopsi itu, {non-empty-string}spesial.
  • $"..." tidak didukung.
  • sebagai kekhasan khusus, ?tidak istimewa ketika mengikuti %(bahkan dikutip atau diperluas) pada awal kata (untuk memungkinkan %?namespesifikasi pekerjaan)
  • sebuah rcquotesopsi (tidak diaktifkan secara default) memungkinkan seseorang untuk memasukkan tanda kutip tunggal sebagai ''tanda kutip tunggal à la rc(lihat di bawah).

yash

seperti POSIXkecuali itu.

  • semua karakter kosong dianggap sebagai pembatas.
  • Dengan brace-expandopsi, mengimplementasikan ekspansi brace gaya zsh.

Untuk semua shell, ada beberapa konteks khusus di mana mengutip bekerja secara berbeda. Kami telah menyebutkan di sini dokumen dan backticks, tetapi ada juga [[...]]di ksh dan beberapa shell lainnya, POSIX $((...)), casekonstruksi ...

Perhatikan juga bahwa mengutip dapat memiliki efek samping lain ketika datang ke ekspansi (dengan tanda kutip ganda), atau ketika diterapkan di sini, pembatas dokumen. Ini juga menonaktifkan kata-kata yang dipesan dan memengaruhi ekspansi alias.

Ringkasan

Dalam cangkang Bourne-like !#$^&*?[(){}<>~;'"`\|=,, SPC, TAB, NEWLINE dan beberapa byte dengan set bit ke-8 adalah atau mungkin spesial (setidaknya dalam beberapa konteks).

Untuk menghapus makna khusus sehingga mereka diperlakukan secara harfiah, Anda menggunakan kutipan.

Menggunakan:

  • '...' untuk menghapus makna khusus setiap karakter:

    printf '%s\n' '\/\/ Those $quoted$ strings are passed literally as
    single arguments (without the enclosing quotes) to `printf`'
  • \ untuk menghapus arti khusus dari satu karakter saja:

    printf '<%s>\n' foo bar\ baz #comment

    Di atas, hanya karakter ruang yang didahului oleh a \yang diteruskan secara harfiah ke printf. Yang lain diperlakukan oleh shell sebagai pembatas token.

  • menggunakan "..."mengutip karakter sementara masih memungkinkan ekspansi parameter ( $var, $#, ${foo#bar}...), ekspansi aritmatika ( $((1+1)), juga $[1+1]di beberapa kerang) dan perintah substitusi ( $(...)atau bentuk lama `...`. Sebenarnya, sebagian besar waktu, Anda ingin menempatkan orang-orang ekspansi di dalam kutip ganda dalam hal apa pun . Anda dapat menggunakan di \dalam "..."untuk menghapus makna khusus dari karakter yang masih istimewa (tetapi hanya mereka).
  • jika string berisi 'karakter, Anda masih dapat menggunakan '...'sisanya dan menggunakan mekanisme kutipan lain yang dapat mengutip 'suka "'"atau \'atau (jika tersedia) $'\'':

    echo 'This is "tricky", isn'\''t it?'
  • Gunakan $(...)bentuk substitusi perintah modern . Hanya gunakan yang lama `...`untuk kompatibilitas dengan shell Bourne, yaitu untuk sistem yang sangat lama, dan hanya dalam penugasan variabel, seperti dalam jangan gunakan:

    echo "`echo "foo bar"`"

    Yang tidak akan bekerja dengan shell Bourne atau AT&T versi ksh. Atau:

    echo "`echo \"foo bar\"`"

    Yang akan bekerja dengan Bourne dan AT&T ksh, tetapi tidak dengan yash, tetapi gunakan:

    var=`echo "foo bar"`; echo "$var"

    yang akan bekerja dengan semua.

    Membuat mereka nyaman dengan tanda kutip ganda juga tidak mungkin, jadi sekali lagi, gunakan variabel. Waspadalah terhadap pemrosesan backslash khusus:

    var=`printf '%s\n' '\\'`

    Hanya akan menyimpan satu backslash di dalam $var, karena ada tingkat pemrosesan backslash tambahan (untuk \, `, dan $(dan juga "ketika dikutip kecuali dalam yash)) dalam backticks sehingga Anda perlu salah

    var=`printf '%s\n' '\\\\'`

    atau

    var=`printf '%s\n' '\\\'

    sebagai gantinya.

Keluarga Csh

csh dan tcsh memiliki sintaks yang sangat berbeda, meskipun masih ada banyak kesamaan dengan cangkang Bourne karena mereka berbagi warisan bersama.

Karakter spesial:

  • "\'&|;()^`<>$, spasi, baris baru dan tab adalah spesial di mana-mana ketika tidak dikutip.
  • #(csh adalah shell yang diperkenalkan #sebagai pemimpin komentar) khusus pada awal skrip atau mengikuti spasi, tab, atau baris baru yang tidak dikutip.
  • *?[ khusus sebagai operator globbing sehingga dalam konteks daftar
  • {non-empty-string} khusus (csh adalah shell yang memperkenalkan ekspansi brace).
  • !dan ^spesial sebagai bagian dari ekspansi sejarah (sekali lagi, penemuan csh), dan aturan mengutip adalah spesial.
  • ~ (Perluasan juga penemuan csh) adalah khusus dalam beberapa konteks.

Mengutip operator

Mereka sama seperti untuk shell Bourne, tetapi perilakunya berbeda. tcsh berperilaku seperti csh dari sudut pandang sintaks, Anda akan menemukan bahwa banyak versi csh memiliki bug jahat. Dapatkan versi terbaru tcsh untuk mendapatkan versi csh yang berfungsi dengan baik.

  • \lolos dari satu karakter kecuali baris baru (sama seperti untuk shell Bourne). Ini satu-satunya operator mengutip yang dapat melarikan diri !. \<newline>tidak menghindarinya tetapi mengubahnya dari pemisah perintah ke pemisah token (seperti spasi)
  • "..."lolos semua karakter kecuali dirinya sendiri, $, `, baris baru dan !. Berlawanan dengan shell Bourne, Anda tidak dapat menggunakan \untuk keluar $dan `masuk "...", tetapi Anda dapat menggunakan \untuk melarikan diri !atau baris baru (tetapi tidak sendiri kecuali ketika sebelum !baris atau baru). Sebuah literal !adalah "\!"dan literal \!adalah "\\!".
  • '...' lolos dari semua karakter kecuali dirinya sendiri, !dan baris baru. Seperti untuk tanda kutip ganda, !dan baris baru dapat lolos dengan backslash.
  • substitusi perintah hanya melalui `...`sintaks dan sulit digunakan secara andal.
  • substitusi variabel juga dirancang dengan buruk dan rawan kesalahan. Seorang $var:qoperator membantu untuk menulis kode yang lebih andal yang melibatkan variabel.

Ringkasan

Tinggal jauh dari csh jika Anda bisa. Jika Anda tidak dapat menggunakan:

  • Kutipan tunggal untuk mengutip sebagian besar karakter. !dan baris baru masih perlu \.
  • \ dapat melarikan diri sebagian besar karakter
  • "..."dapat memungkinkan beberapa ekspansi di dalamnya, tapi itu cukup buggy jika mereka menyematkan baris baru dan / atau karakter backslash, mungkin yang terbaik adalah menggunakan tanda kutip tunggal saja dan $var:quntuk ekspansi variabel. Anda harus menggunakan loop jika Anda ingin menggabungkan elemen-elemen array dengan andal.

rc keluarga

rcadalah plan9shell dan seperti keturunannya esdan akangatelah porting ke Unix dan suka-unix. Itu shell dengan sintaks yang jauh lebih bersih dan lebih baik dan yang semua orang akan gunakan jika kita tidak terjebak dengan shell Bourne-like untuk kompatibilitas mundur.

rc/akanga

Karakter spesial

  • #;&|^$=`'{}()<>, SPC, TAB dan NEWLINE selalu istimewa ketika tidak dikutip.
  • *?[ adalah operator globbing.

Operator mengutip

'...'adalah satu-satunya operator yang mengutip. Litteral 'ditulis dengan ''tanda kutip tunggal seperti pada:

 echo 'it''s so simple isn''t it?'

es

esdapat dilihat sebagai shell eksperimental berdasarkan rc.

Ini memiliki beberapa perbedaan. Yang menarik dari Tanya Jawab ini adalah bahwa \ia juga merupakan operator mengutip (yang mengutip semua karakter khusus kecuali baris baru) dan juga dapat digunakan untuk memperkenalkan urutan pelarian seperti \nuntuk baris baru, \buntuk garis miring terbalik ...

ikan

ikan adalah pendatang baru (sekitar tahun 2005), terutama ditujukan untuk penggunaan interaktif dan juga memiliki sintaks yang sangat berbeda dari kerang lain.

karakter spesial

  • "'\()$%{}^<>;&|selalu istimewa ketika tidak dikutip (perhatikan %(untuk ekspansi pid) sebagai perbedaan yang signifikan dari cangkang lain, dan `tidak istimewa)
  • # (komentar) khusus ketika mengikuti spasi, tab, baris baru atau ;&|^<>
  • *?(tetapi tidak [...]) operator globbing

Mengutip operator

  • \mengutip satu karakter khusus kecuali baris baru, tetapi waspadalah juga berfungsi sebagai pengantar pelarian C ( \n, \b...). TKI, \nbukan kutipan ntapi baris baru.
  • "..."mengutip segalanya kecuali dirinya sendiri, $dan backslash dan backslash dapat digunakan untuk melarikan diri dari itu. \<newline>adalah kelanjutan garis (dihapus) di dalam "...".
  • '...'mengutip semuanya kecuali dirinya sendiri dan \, dan Anda dapat menggunakan backslash untuk melarikan diri dari itu.
Stéphane Chazelas
sumber
Saya telah memasukkan hanya yang khusus dalam semua konteks (sehingga cbertindak sama seperti \c, ctidak menghasilkan c: command not foundpada STDERR, dll.) Dan saya bicarakan di shsini. Juga, ingat bahwa ini adalah pertanyaan "pembersihan", yaitu pertanyaan ini ada di sini untuk mencakup semua karakter tersebut, jadi 19+ pertanyaan tidak perlu ditanyakan. Pertanyaan telah diposting berkat insiden bahwa berbagai pertanyaan diajukan untuk karakter yang berbeda, kami pasti ingin membersihkan di sini!
EKons
Ya, ?[memang operator globbing, tetapi tidak spesial dalam semua konteks, tetapi *sepertinya, karena echo *buruknya echoisi direktori saat ini (tidak melarikan diri dari apa pun). echo ?gema literal ?dan echo [gema literal [. Juga, ]adalah oberator globbing juga.
EKons
1
@ ΈρικΚωνσταντόπουλος, *saat gumpalan diperluas ke semua file yang ?tidak tersembunyi, [a-z]ke file karakter tunggal yang tidak tersembunyi, ke file yang namanya adalah karakter tunggal antara a dan z dan seterusnya. Ketika mereka tidak cocok dengan file apa pun (seperti dalam kasus Anda untuk ?), tergantung pada shell, Anda mendapatkan kesalahan tidak cocok atau polanya berkembang dengan sendirinya. Dalam kasus apa pun, bahkan pada shell di mana mereka berkembang untuk diri mereka sendiri, mereka perlu dikutip jika mereka dapat mencocokkan file.
Stéphane Chazelas
Tapi, bukan sebagai bola, *masih melebar ke sesuatu.
EKons
@ ΈρικΚωνσταντόπουλος, *adalah seperti ?, jika tidak cocok (untuk kasus *sendirian, saat itulah hanya ada file tersembunyi di direktori saat ini, karena a*di situlah tidak ada file yang namanya dimulai dengan a...), itu dapat diperluas ke itu sendiri (paling Bourne-seperti kerang), atau menimbulkan kesalahan ada pertandingan ( csh, tcsh, fish(peringatan), zsh, bash -O failglob, awal Unix kerang), (atau mengembang apa-apa dengan pilihan nullglob beberapa kerang atau jika ada pola lain yang mengembang ke sesuatu di csh, tcsh, zsh -o cshnullglob, shell unix awal).
Stéphane Chazelas
4

1. Melarikan diri

Lari semua karakter ini dengan \, seperti ini (tidak berfungsi pada baris baru / pengembalian kereta):

$ echo Use a \"\\\" symbol to escape characters.
Use a "\" symbol to escape characters.

2. Kutipan ganda

Lampirkan seluruh teks dalam "s, seperti ini:

$ var=variables;echo "Enclose text in \"s. You can also use $var in them. `echo Surprise!!!`"
Enclose text in "s. You can also use variables in them. Surprise!!!

3. Kutipan tunggal

Sama seperti double-quote, tetapi tidak ada token khusus.

$ proof=proveit;echo 'This should not read "proveit": $proof'
This should not read "proveit": $proof
EKons
sumber
1
Anda menggambarkan perilaku fishshell, bukan shell seperti Bourne di mana kutipan tunggal mengutip setiap karakter (backslash tidak spesial di dalam'...' ). Perhatikan bahwa dalam fish, %juga merupakan karakter khusus.
Stéphane Chazelas
@ StéphaneChazelas Saya tidak tahu cara fishkerjanya, tapi pengalaman saya adalah itu, di sh, echo '\\'gema\ dan echo '\''gema '.
EKons
1
echo '\\'output \ karena Anda echomemperluas urutan pelarian ANSI C (beberapa echoimplementasi perlu echo -e '\\'untuk itu). printf '%s\n' '\\'output \\.
Stéphane Chazelas
Catatan yang shtidak mengidentifikasi shell tertentu, ada dan telah banyak disebut shell berbeda dan sering tidak kompatibel sh.
Stéphane Chazelas
@ StéphaneChazelas Oh oke, saya akan mengubahnya sekarang. Omong-omong, apakah \'token khusus di dalam urutan karakter yang dikutip tunggal?
EKons