GNU/Linux >> Belajar Linux >  >> Linux

Bagaimana Cara Menggunakan Karakter Khusus Sebagai Karakter Normal Di Unix Shells?

Banyak pertanyaan seperti 'Bagaimana cara mengetik karakter tanda kutip ganda (“)?’ yang ditanyakan, dan kami tidak ingin mengacaukan komunitas kami dengan jawaban yang sama (Ketik sebagai " jika tidak diapit ' s, " jika dilampirkan dalam ' s.) Jadi, pertanyaannya ada di sini.

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

echo Updates (11)

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

!#$^&*?[](){}<>~;'"|<space><tab><newline>

Jawaban yang Diterima:

Itu sangat tergantung pada cangkangnya. 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 khusus di awal kata atau mengikuti beberapa karakter seperti : . Sama untuk = di zsh . Di beberapa shell, [ hanya spesial jika dicocokkan (dengan beberapa batasan) dengan ] .

Di beberapa shell seperti bash atau yash , karakter khusus seperti pembatas token kosong juga bervariasi menurut lokal.

Operator kutipan (untuk menghilangkan arti khusus dari karakter tersebut) juga sangat bervariasi antar shell.

Kerang mirip Bourne

Ringkasan untuk cangkang mirip Bourne (yaitu cangkang yang dikenal sebagai sh pada beberapa sistem atau lainnya sejak tahun 80-an):

kulit Bourne

Karakter khusus:

  • "'&|;()^`<>$ , spasi, baris baru, dan tab khusus dalam baris perintah sederhana saat tidak dikutip.
  • # (kecuali di versi awal) khusus di awal baris atau setelah spasi, tab atau &|()^<>;` yang tidak diberi tanda kutip .
  • { dan } hanya khusus karena mereka adalah kata kunci shell (jadi hanya kata-kata di posisi perintah).
  • *?[ khusus sebagai operator globbing, jadi hanya dalam konteks daftar. Dalam kasus [ , ini [...] itu adalah operator globbing, baik [ atau ] hanya perlu dikutip untuk menghilangkan arti khusus.
  • = khusus ketika dalam konteks di mana ia diperlakukan sebagai operator penugasan. Yaitu, 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 logis long yang panjang baris ke fisik berikutnya baris, sehingga urutan dihapus). Perhatikan bahwa backtick menambah kerumitan ekstra seperti di dalamnya, digunakan terlebih dahulu untuk menghindari backtick penutup dan membantu parser. Di dalam tanda kutip ganda, hanya dapat digunakan untuk melarikan diri, " , $ dan ` (<newline> masih merupakan kelanjutan garis). Di dalam dokumen di sini, sama kecuali untuk " . adalah satu-satunya cara untuk keluar dari karakter di dalam dokumen di sini.
  • "..." tanda kutip ganda keluar dari semua karakter kecuali dirinya sendiri, , $ dan ` .
  • '...' tanda kutip tunggal keluar dari semua karakter kecuali dirinya sendiri.

Shell POSIX

Shell POSIX sebagian besar berperilaku seperti shell Bourne, kecuali bahwa:

  • ^ bukan lagi karakter khusus
  • ~ istimewa dalam beberapa konteks
  • { diperbolehkan untuk menjadi khusus sehingga harus dikutip.

ksh

seperti POSIX kecuali bahwa:

  • {string} khusus jika string berisi , . yang tidak dikutip (atau .. dalam beberapa kasus dan dengan beberapa versi).
  • ksh93 memiliki operator kutipan khusus tambahan:$'...' dengan aturan yang kompleks. Operator itu juga ditemukan (dengan beberapa variasi) di bash , zsh , mksh dan FreeBSD dan busybox sh .
  • ksh93 juga memiliki $"..." mengutip operator yang berfungsi seperti "..." kecuali bahwa string tunduk pada pelokalan (dapat dikonfigurasi sehingga diterjemahkan ke bahasa pengguna). mksh mengabaikan $ di $"..." .
  • sejak ksh93r , ksh93 mendukung csh-style (tidak diaktifkan secara default) dengan -H / -o histexpand dalam cangkang interaktif) yang membuat ^ di awal perintah dan ! spesial. ! kemudian khusus dalam beberapa konteks (tidak ketika diikuti oleh spasi atau TAB atau di sini dokumen) dan tidak diloloskan oleh tanda kutip ganda. Hanya garis miring terbalik (tidak dalam tanda kutip ganda) dan tanda kutip tunggal yang lolos.

bash

seperti ksh93 tapi:

  • dalam lokal karakter byte tunggal, semua kosong (menurut lokal) karakter dianggap sebagai pembatas (seperti spasi atau tab). Akibatnya, itu berarti Anda harus mengutip semua byte dengan set bit ke-8 jika mereka mungkin berupa karakter kosong di beberapa lokal.
  • ekspansi riwayat csh diaktifkan secara default dalam instance interaktif, dengan catatan yang sama seperti pada ksh93 di atas kecuali dalam versi bash yang lebih baru , ! terkadang juga tidak istimewa, jika diikuti oleh " .

zsh

seperti ksh93 tapi:

  • catatan yang sama dengan bash untuk perluasan riwayat csh
  • = khusus sebagai karakter pertama dari sebuah kata (=ls diperluas ke /bin/ls ).
  • { dan } juga dapat membuka dan menutup grup perintah jika tidak dibatasi (seperti dalam {echo text} bekerja seperti { echo text;} Bo Bourne ).
  • kecuali [ sendirian, [ perlu dikutip meskipun tidak ditutup dengan ] .
  • Dengan extendedglob opsi diaktifkan, # , ^ dan ~ adalah operator globbing.
  • Dengan braceccl opsi, {non-empty-string} istimewa.
  • $"..." tidak didukung.
  • sebagai kekhasan khusus, ? tidak istimewa saat mengikuti % (bahkan dikutip atau diperluas) di awal kata (untuk mengizinkan %?name spesifikasi pekerjaan)
  • sebuah rcquotes option (tidak diaktifkan secara default) memungkinkan seseorang untuk memasukkan tanda kutip tunggal sebagai '' di dalam tanda kutip tunggal la rc (lihat di bawah).
Terkait:Apakah LVM memengaruhi kinerja?

yash

seperti POSIX kecuali itu.

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

Untuk semua shell, ada beberapa konteks khusus di mana kutipan bekerja secara berbeda. Kami telah menyebutkan di sini dokumen dan backtick, tetapi ada juga [[...]] di ksh dan beberapa shell lainnya, POSIX $((...)) , case konstruksi…

Perhatikan juga bahwa mengutip dapat memiliki efek samping lain dalam hal ekspansi (dengan tanda kutip ganda), atau bila diterapkan di sini pembatas dokumen. Ini juga menonaktifkan kata-kata yang dicadangkan dan memengaruhi perluasan alias.

Ringkasan

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

Untuk menghilangkan arti khusus agar diperlakukan secara harfiah, gunakan kutipan.

Gunakan:

  • '...' untuk menghilangkan arti khusus dari setiap karakter:

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

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

    Di atas, hanya karakter spasi yang diawali dengan diteruskan secara harfiah ke printf . Yang lainnya diperlakukan oleh shell sebagai pembatas token.

  • gunakan "..." untuk mengutip karakter sambil tetap mengizinkan perluasan parameter ($var , $# , ${foo#bar} …), ekspansi aritmatika ($((1+1)) , juga $[1+1] di beberapa shell) dan substitusi perintah ($(...) atau bentuk lama `...` . Sebenarnya, sebagian besar waktu, Anda ingin menempatkan ekspansi tersebut di dalam tanda kutip ganda. Anda dapat menggunakan dalam "..." untuk menghilangkan arti khusus dari karakter yang masih istimewa (tetapi hanya mereka).

  • jika string berisi ' karakter, Anda masih dapat menggunakan '...' selebihnya dan gunakan mekanisme kutipan lain yang dapat mengutip ' seperti "'" atau ' atau (jika tersedia) $''' :

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

    echo "`echo "foo bar"`"
    

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

    echo "`echo "foo bar"`"
    

    Yang akan bekerja dengan Bourne dan AT&T ksh, tetapi tidak dengan yash (Suntingan tahun 2020: hanya di versi 2.41 dan sebelumnya, sudah diubah di 2.42 / laporan bug / komit), tetapi gunakan:

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

    yang akan bekerja dengan semua.

    Menyarangkannya secara portabel dengan tanda kutip ganda juga tidak mungkin, jadi sekali lagi, gunakan variabel. Juga berhati-hatilah dengan pemrosesan backslash khusus:

    var=`printf '%sn' '\'`
    

    Akan menyimpan hanya satu garis miring terbalik di dalam $var , karena ada tingkat ekstra pemrosesan garis miring terbalik (untuk , `, dan $ (dan juga " ketika dikutip kecuali dalam yash )) dalam backticks sehingga Anda memerlukannya

    var=`printf '%sn' '\\'`
    

    atau

    var=`printf '%sn' '\'
    

    sebagai gantinya.

Keluarga Csh

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

Karakter khusus:

  • "'&|;()^`<>$ , spasi, baris baru, dan tab istimewa di mana saja jika tidak dikutip.
  • # (csh adalah shell yang memperkenalkan # sebagai pemimpin komentar) khusus di awal skrip atau setelah spasi, tab, atau baris baru tanpa tanda kutip.
  • *?[ khusus sebagai operator globbing jadi dalam konteks daftar
  • {non-empty-string} khusus (csh adalah shell yang memperkenalkan ekspansi brace).
  • ! dan ^ khusus sebagai bagian dari perluasan sejarah (sekali lagi, penemuan csh), dan aturan mengutip adalah istimewa.
  • ~ (ekspansi tilde juga merupakan penemuan csh) 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 tcsh versi terbaru untuk mendapatkan versi csh yang berfungsi dengan baik.

  • lolos dari satu karakter kecuali baris baru (sama seperti untuk Bourne Shell). Ini adalah satu-satunya operator kutipan yang dapat keluar dari ! . <newline> tidak menghindarinya tetapi mengubahnya dari pemisah perintah menjadi pemisah token (seperti spasi)
  • "..." lolos dari semua karakter kecuali dirinya sendiri, $ , ` , baris baru dan ! . Bertentangan dengan shell Bourne, Anda tidak dapat menggunakan untuk keluar dari $ dan ` di dalam "..." , tetapi Anda dapat menggunakan untuk keluar dari ! atau baris baru (tetapi bukan dirinya sendiri kecuali jika sebelum ! atau baris baru). ! adalah "!" dan ! . literal adalah "\!" .
  • '...' lolos dari semua karakter kecuali dirinya sendiri, ! dan baris baru. Seperti untuk tanda kutip ganda, ! dan baris baru dapat diloloskan dengan garis miring terbalik.
  • penggantian perintah hanya melalui `...` sintaks dan hampir tidak dapat digunakan dengan andal.
  • Substitusi variabel juga dirancang dengan sangat buruk dan rawan kesalahan. Sebuah $var:q operator membantu menulis kode yang lebih andal yang melibatkan variabel.
Terkait:Di mana Operasi Khusus Tempel Excel di Google Sheets?

Ringkasan

Jauhi csh jika Anda bisa. Jika Anda tidak dapat menggunakan:

  • kutipan tunggal untuk mengutip sebagian besar karakter. ! dan baris baru masih membutuhkan .
  • dapat menghindari sebagian besar karakter
  • "..." dapat mengizinkan beberapa ekspansi di dalamnya, tetapi itu cukup bermasalah jika mereka menyematkan karakter baris baru dan/atau garis miring terbalik, sebaiknya gunakan tanda kutip tunggal saja dan $var:q untuk ekspansi variabel. Anda harus menggunakan loop jika ingin menggabungkan elemen array dengan andal.

rc keluarga

rc adalah plan9 shell dan seperti turunannya es dan akanga telah di-porting ke Unix dan unix-likes. Itu adalah shell dengan sintaks yang jauh lebih bersih dan lebih baik dan yang akan digunakan semua orang jika kita tidak terjebak dengan shell seperti Bourne untuk kompatibilitas mundur.

rc /akanga

Karakter khusus

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

Operator kutipan

'...' adalah satu-satunya operator kutipan. Sebuah ' ditulis dengan '' dalam tanda kutip tunggal seperti pada:

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

es

es bisa dilihat sebagai eksperimen shell berdasarkan rc .

Ini memiliki beberapa perbedaan. Yang menarik untuk Q/A ini adalah juga merupakan operator kutipan (yang mengutip semua karakter khusus kecuali baris baru) dan juga dapat digunakan untuk memperkenalkan urutan escape seperti n untuk baris baru, b untuk garis miring terbalik…

ikan

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

karakter khusus

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

Mengutip operator

  • mengutip satu karakter khusus kecuali baris baru, tetapi berhati-hatilah karena itu juga berfungsi ganda sebagai urutan escape C (n , b ...) pengantar. TKI, n bukan n quoted yang dikutip tapi baris baru.
  • "..." mengutip semuanya kecuali dirinya sendiri, $ dan garis miring terbalik dan garis miring terbalik dapat digunakan untuk menghindarinya. <newline> adalah kelanjutan baris (dihapus) di dalam "..." .
  • '...' mengutip semuanya kecuali dirinya sendiri dan , dan Anda dapat menggunakan garis miring terbalik untuk menghindarinya.

Linux
  1. UNIX / Linux:Cara Menggunakan Sticky Bit pada Direktori dan File

  2. Cara menggunakan lookahead untuk mengecualikan karakter khusus dalam ekspresi reguler

  3. Bagaimana cara mengidentifikasi distro linux yang digunakan?

  1. Bagaimana saya menggunakan cron di Linux

  2. Cara Menggunakan Nginx untuk Mengarahkan

  3. Bagaimana Cara Menggunakan Command Coproc Di Berbagai Shell?

  1. Apa Karakter Khusus Dan Blokir File Khusus Dalam Sistem Unix??

  2. Cara menggunakan perintah netstat di Linux (Contoh disertakan)

  3. Cara menggunakan ekspansi shell untuk menghasilkan token shell di Linux