Làm thế nào để sử dụng một nhân vật đặc biệt như một người bình thường?


13

Nhiều câu hỏi như 'Làm thế nào để gõ char trích dẫn kép (")?' đang được hỏi và chúng tôi không muốn làm lộn xộn cộng đồng của mình với cùng một câu trả lời (Nhập nó như \"thể không được đặt trong 's, "nếu được đặt trong 's.) Vì vậy, câu hỏi nằm ở đây.

Bạn không thể nhập ký tự đặc biệt vào thiết bị đầu cuối như thiết bị đầu cuối thông thường, ví dụ: lệnh này sẽ thất bại:

echo Updates (11)

Vì vậy, làm thế nào để gõ những ký tự này trong thiết bị đầu cuối như thể chúng là bình thường?

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

Không có vỏ Unix mà tôi biết nơi vận chuyển trở lại là đặc biệt. =, @%đặc biệt trong một số vỏ trong một số bối cảnh.
Stéphane Chazelas

@ StéphaneChazelas Umm ... car car return ( ^M) hoạt động giống như nguồn cấp dữ liệu ( ^J) cho tôi (Ubuntu 14.04, sh).
EKons

Không, trình điều khiển thiết bị đầu cuối của bạn chuyển đổi ^Mthành ^Jđầu vào nhưng ^Mkhông đặc biệt với trình bao và không cần trích dẫn. Nhập echo ^V^M | hdvà bạn sẽ thấy ký tự 0d (và 0a được thêm vào bởi tiếng vang).
Stéphane Chazelas

@ StéphaneChazelas Umm ... Tôi không biết cái gì hd, có lẽ xxdtốt hơn khi xem hex.
EKons

Cái nào cũng được. Sử dụng POSIX od -tx1hoặc sed -n lxx's xxd nếu bạn không có hd. Một số hệ thống cũng có cat -vtehoặccat -A
Stéphane Chazelas

Câu trả lời:


26

Điều đó phụ thuộc rất nhiều vào vỏ. Kiểm tra hướng dẫn sử dụng vỏ của bạn để biết chi tiết.

Cũng lưu ý rằng một số nhân vật chỉ đặc biệt trong một số bối cảnh. Ví dụ, trong hầu hết các shell *?chỉ đặc biệt trong ngữ cảnh danh sách, trong các shell giống POSIX hoặc csh, ~chỉ đặc biệt ở đầu từ hoặc theo một số ký tự như :. Tương tự cho =trong zsh. Trong một số shell, [chỉ đặc biệt khi khớp (với một số hạn chế) bởi a ].

Trong một số shell như bashhoặc yash, các ký tự đặc biệt như dấu phân cách mã thông báo trống cũng thay đổi theo miền địa phương.

Các toán tử trích dẫn (để loại bỏ ý nghĩa đặc biệt của các ký tự đó) cũng khác nhau rất nhiều giữa các shell.

Vỏ sò giống như Bourne

Một bản tóm tắt cho các shell giống như Bourne (đó là các shell đã được gọi là được gọi shtrên một số hệ thống hoặc hệ thống khác kể từ những năm 80):

Vỏ Bourne

Nhân vật đặc biệt:

  • "\'&|;()^`<>$, dấu cách, dòng mới và tab là đặc biệt trong các dòng lệnh đơn giản khi không được trích dẫn.
  • #(ngoại trừ trong phiên bản đầu) là đặc biệt ở đầu một dòng hoặc theo sau một khoảng trắng, tab hoặc &|()^<>;`.
  • {}chỉ đặc biệt ở chỗ chúng là các từ khóa shell (vì vậy chỉ các từ ở vị trí lệnh).
  • *?[là đặc biệt như các nhà khai thác toàn cầu, vì vậy chỉ trong bối cảnh danh sách. Trong trường hợp [, đó [...]là toán tử toàn cầu, [hoặc ]chỉ cần được trích dẫn để loại bỏ ý nghĩa đặc biệt.
  • =là đặc biệt khi trong bối cảnh nơi nó được coi là toán tử gán. Đó là, trong một lệnh đơn giản, cho tất cả các từ không tuân theo một đối số (ngoại trừ sau set -k).

Trích dẫn điều hành

  • \trích dẫn tất cả các ký tự đặc biệt ngoại trừ dòng mới ( \<newline>là một cách để tiếp tục một dòng logic dài vào dòng vật lý tiếp theo , để chuỗi đó được loại bỏ). Lưu ý rằng backticks thêm độ phức tạp như bên trong chúng, \được sử dụng trước tiên để thoát backtick đóng và giúp trình phân tích cú pháp. Bên trong dấu ngoặc kép, \chỉ có thể được sử dụng để thoát thân, ", $`( \<newline>vẫn còn là một tự tiếp tục dòng). Bên trong một tài liệu ở đây, tương tự ngoại trừ ". \là cách duy nhất để thoát khỏi các nhân vật bên trong các tài liệu ở đây.
  • "..."dấu ngoặc kép thoát tất cả các ký tự nhưng chính nó \, $`.
  • '...' trích dẫn duy nhất thoát khỏi tất cả các nhân vật nhưng chính nó.

Vỏ POSIX

Vỏ POSIX hoạt động chủ yếu giống như vỏ Bourne, ngoại trừ:

ksh

như POSIX ngoại trừ:

  • {string}là đặc biệt nếu chuỗi chứa một chuỗi không trích dẫn ,(hoặc ..trong một số trường hợp và với một số phiên bản).
  • ksh93 có một toán tử trích dẫn đặc biệt bổ sung: $'...'với các quy tắc phức tạp. Nhà điều hành mà cũng được tìm thấy (với một số biến thể) trong bash, zsh, mkshvà FreeBSD và busybox sh.
  • ksh93cũng có một $"..."toán tử trích dẫn hoạt động như "..."ngoại trừ chuỗi có thể được bản địa hóa (có thể được cấu hình để nó dịch sang ngôn ngữ của người dùng). mkshbỏ qua $trong $"...".

bash

thích ksh93nhưng:

  • trong các ký tự byte đơn, tất cả các ký tự trống (theo miền địa phương) được coi là các dấu phân cách (như khoảng trắng hoặc tab). Trong thực tế, điều đó có nghĩa là bạn nên trích dẫn tất cả các byte với bit thứ 8 được đặt trong trường hợp chúng có thể là một ký tự trống trong một số ngôn ngữ.
  • Khi mở rộng lịch sử csh được kích hoạt như trong các trường hợp tương tác, !đặc biệt trong một số bối cảnh và dấu ngoặc kép không phải lúc nào cũng thoát khỏi nó. Và ^là đặc biệt khi bắt đầu một lệnh.

zsh

thích ksh93nhưng:

  • lưu ý tương tự như đối bashvới mở rộng lịch sử csh
  • =là đặc biệt như ký tự đầu tiên của một từ ( =lsmở rộng đến /bin/ls).
  • {}cũng có thể mở và đóng các nhóm lệnh khi không được phân định (như trong {echo text}các tác phẩm như của Bourne { echo text;}).
  • ngoại trừ [một mình, [cần trích dẫn ngay cả khi không đóng với a ].
  • Với extendedglobtùy chọn được kích hoạt #, ^~là các toán tử toàn cầu.
  • Với braceccltùy chọn, {non-empty-string}là đặc biệt.
  • $"..." không được hỗ trợ.
  • như một cách giải quyết đặc biệt, ?không đặc biệt khi tuân theo một %(thậm chí được trích dẫn hoặc mở rộng) khi bắt đầu một từ (để cho phép %?nameđặc tả công việc)
  • một rcquotestùy chọn (không được bật theo mặc định) cho phép một người nhập các dấu ngoặc đơn như ''bên trong dấu ngoặc đơn à la rc(xem bên dưới).

yash

thích POSIXngoại trừ đó

  • tất cả các ký tự trống được coi là dấu phân cách.
  • Với brace-expandtùy chọn, thực hiện mở rộng nẹp kiểu zsh.

Đối với tất cả các shell, có một số bối cảnh đặc biệt trong đó trích dẫn hoạt động khác nhau. Chúng tôi đã đề cập ở đây các tài liệu và backticks, nhưng cũng có [[...]]trong ksh và một vài shell khác, POSIX $((...)), các casecấu trúc ...

Cũng lưu ý rằng trích dẫn có thể có tác dụng phụ khác khi nói đến việc mở rộng (với dấu ngoặc kép) hoặc khi áp dụng cho các dấu phân cách tài liệu ở đây. Nó cũng vô hiệu hóa các từ dành riêng và ảnh hưởng đến việc mở rộng bí danh.

Tóm lược

Trong các shell giống như Bourne !#$^&*?[(){}<>~;'"`\|=, SPC, TAB, NEWLINE và một số byte với tập bit thứ 8 là hoặc có thể đặc biệt (ít nhất là trong một số ngữ cảnh).

Để loại bỏ ý nghĩa đặc biệt để chúng được xử lý theo nghĩa đen, bạn sử dụng trích dẫn.

Sử dụng:

  • '...' để loại bỏ ý nghĩa đặc biệt của mỗi nhân vật:

    printf '%s\n' '\/\/ Those $quoted$ strings are passed literally as
    single arguments (without the enclosing quotes) to `printf`'
  • \ để loại bỏ ý nghĩa đặc biệt của chỉ một ký tự:

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

    Ở trên, chỉ có ký tự không gian đứng trước a \được truyền theo nghĩa đen printf. Những cái khác được xử lý bởi shell là dấu phân cách mã thông báo.

  • sử dụng "..."trích dẫn các nhân vật trong khi vẫn cho phép mở rộng tham số ( $var, $#, ${foo#bar}...), mở rộng số học ( $((1+1))cũng $[1+1]trong một số vỏ) và thay thế lệnh ( $(...)hoặc các hình thức cũ `...`. Trên thực tế, hầu hết thời gian, bạn muốn đặt những mở rộng bên trong dấu ngoặc kép trong mọi trường hợp . Bạn có thể sử dụng \bên trong "..."để loại bỏ ý nghĩa đặc biệt của các ký tự vẫn còn đặc biệt (nhưng chỉ chúng).
  • nếu chuỗi chứa 'ký tự, bạn vẫn có thể sử dụng '...'cho phần còn lại và sử dụng các cơ chế trích dẫn khác có thể trích dẫn 'như "'"hoặc \'hoặc (nếu có) $'\'':

    echo 'This is "tricky", isn'\''t it?'
  • Sử dụng $(...)hình thức thay thế lệnh hiện đại . Chỉ sử dụng cái cũ `...`để tương thích với shell Bourne, nghĩa là hệ thống rất cũ và chỉ trong các bài tập thay đổi, như trong không sử dụng:

    echo "`echo "foo bar"`"

    Không hoạt động với phiên bản vỏ Bourne hoặc phiên bản AT & T của ksh. Hoặc là:

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

    Cái nào sẽ hoạt động với Bourne và AT & T ksh, nhưng không phải với yash, nhưng sử dụng:

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

    mà sẽ làm việc với tất cả.

    Việc lồng chúng một cách hợp lý với dấu ngoặc kép cũng là không thể, vì vậy, một lần nữa, sử dụng các biến. Cũng hãy cẩn thận với việc xử lý dấu gạch chéo ngược đặc biệt:

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

    Sẽ chỉ lưu trữ một dấu gạch chéo ngược bên trong $var, bởi vì có thêm một mức xử lý dấu gạch chéo ngược (cho \, `và $(và cả "khi được trích dẫn ngoại trừ trong yash)) trong các backticks vì vậy bạn cần một trong hai

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

    hoặc là

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

    thay thế.

Gia đình Csh

csh và tcsh có một cú pháp khác nhau đáng kể, mặc dù vẫn có nhiều điểm chung với shell Bourne khi chúng có chung một di sản.

Nhân vật đặc biệt:

  • "\'&|;()^`<>$, không gian, dòng mới và tab là đặc biệt ở mọi nơi khi không được trích dẫn.
  • #(csh là hệ vỏ được giới thiệu #là người lãnh đạo nhận xét) là đặc biệt ở phần đầu của tập lệnh hoặc theo một khoảng trắng, tab hoặc dòng mới không được trích dẫn.
  • *?[ là đặc biệt như các nhà khai thác toàn cầu vì vậy trong bối cảnh danh sách
  • {non-empty-string} là đặc biệt (csh là vỏ giới thiệu mở rộng cú đúp).
  • !^đặc biệt như là một phần của việc mở rộng lịch sử (một lần nữa, một phát minh csh) và các quy tắc trích dẫn là đặc biệt.
  • ~ (mở rộng dấu ngã cũng là một phát minh csh) là đặc biệt trong một số bối cảnh.

Trích dẫn điều hành

Chúng giống như đối với vỏ Bourne, nhưng hành vi khác nhau. tcsh hoạt động như csh theo quan điểm cú pháp, bạn sẽ thấy rằng nhiều phiên bản của csh có lỗi khó chịu. Nhận phiên bản mới nhất của tcsh để có được phiên bản csh hoạt động mạnh.

  • \thoát khỏi một ký tự duy nhất ngoại trừ dòng mới (giống như đối với shell Bourne). Đó là toán tử trích dẫn duy nhất có thể thoát !. \<newline>không thoát khỏi nó mà chuyển đổi nó từ một dấu tách lệnh thành một dấu tách mã thông báo (như khoảng trắng)
  • "..."thoát tất cả các nhân vật ngoại trừ bản thân, $, `, xuống dòng và !. Trái ngược với vỏ Bourne, bạn không thể sử dụng \để thoát $`bên trong "...", nhưng bạn có thể sử dụng \để thoát !hoặc dòng mới (nhưng không phải ngoại trừ khi trước một !hoặc dòng mới). Một nghĩa đen !"\!"và một nghĩa đen \!"\\!".
  • '...' thoát tất cả các nhân vật ngoại trừ chính nó, !và dòng mới. Giống như dấu ngoặc kép, !và dòng mới có thể được thoát bằng dấu gạch chéo ngược.
  • thay thế lệnh chỉ thông qua `...`cú pháp và khó có thể được sử dụng một cách đáng tin cậy.
  • thay thế cũng được thiết kế khá xấu và dễ bị lỗi. Một $var:qtoán tử giúp viết mã đáng tin cậy hơn liên quan đến các biến.

Tóm lược

Tránh xa csh nếu bạn có thể. Nếu bạn không thể sử dụng:

  • trích dẫn duy nhất để trích dẫn hầu hết các nhân vật. !và dòng mới vẫn cần a \.
  • \ có thể thoát khỏi hầu hết các nhân vật
  • "..."có thể cho phép một số mở rộng bên trong nó, nhưng đó là lỗi khá lớn nếu chúng nhúng các ký tự dòng mới và / hoặc dấu gạch chéo ngược, tốt nhất có thể là chỉ sử dụng dấu ngoặc đơn và $var:qđể mở rộng biến. Bạn sẽ cần sử dụng các vòng lặp nếu bạn muốn tham gia các phần tử của một mảng đáng tin cậy.

rc gia đình

rcplan9vỏ và giống như hậu duệ của nó esakangađã được chuyển sang Unix và unix- like . Đó là một shell với cú pháp rõ ràng và tốt hơn nhiều và mọi người sẽ sử dụng nếu chúng ta không bị mắc kẹt với các shell giống như Bourne để tương thích ngược.

rc/akanga

Nhân vật đặc biệt

  • #;&|^$=`'{}()<>, SPC, TAB và NEWLINE luôn đặc biệt khi không được trích dẫn.
  • *?[ là các nhà khai thác toàn cầu.

Trích dẫn điều hành

'...'là toán tử trích dẫn duy nhất. Một lứa 'được viết với ''trong dấu ngoặc đơn như trong:

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

es

escó thể được xem như một vỏ thử nghiệm dựa trên rc.

Nó có một vài sự khác biệt mặc dù. Một điều thú vị cho Q / A này \là một toán tử trích dẫn (trích dẫn tất cả các ký tự đặc biệt ngoại trừ dòng mới) và cũng có thể được sử dụng để giới thiệu các chuỗi thoát như \ncho dòng mới, \bcho dấu gạch chéo ngược ...

cá là một người mới đến tương đối (khoảng năm 2005), chủ yếu dành cho sử dụng tương tác và cũng có một cú pháp khác biệt đáng kể so với các loại vỏ khác.

nhân vật đặc biệt

  • "'\()$%{}^<>;&|luôn luôn đặc biệt khi không được trích dẫn (lưu ý %(đối với mở rộng pid) là một sự khác biệt đáng kể so với các shell khác và `không đặc biệt)
  • # (bình luận) đặc biệt khi theo dõi không gian không được trích dẫn, tab, dòng mới hoặc ;&|^<>
  • *?(nhưng không [...]) các nhà khai thác toàn cầu

Trích dẫn điều hành

  • \trích dẫn một ký tự đặc biệt ngoại trừ dòng mới, nhưng hãy cẩn thận, nó cũng tăng gấp đôi như một trình tự thoát C ( \n, \b...). IOW, \nkhông phải là một trích dẫn nmà là một dòng mới.
  • "..."trích dẫn tất cả mọi thứ trừ chính nó, $và dấu gạch chéo ngược và dấu gạch chéo ngược có thể được sử dụng để thoát khỏi chúng. \<newline>là một dòng tiếp tục (loại bỏ) bên trong "...".
  • '...'trích dẫn tất cả mọi thứ trừ chính nó và \, và bạn có thể sử dụng dấu gạch chéo ngược để thoát khỏi những thứ đó.

Tôi chỉ bao gồm những cái đặc biệt trong tất cả các bối cảnh (để nó choạt động giống như \c, ckhông xuất ra c: command not foundtrên STDERR, v.v.) Và tôi đang nói về vấn đề shnày. Ngoài ra, hãy nhớ rằng đây là một câu hỏi "dọn dẹp", tức là nó ở đây để bao gồm tất cả các nhân vật như vậy, vì vậy 19+ câu hỏi sẽ không phải hỏi. Câu hỏi đã được đăng lên nhờ một sự cố mà các câu hỏi khác nhau được yêu cầu cho các nhân vật khác nhau như vậy, chúng tôi chắc chắn muốn làm sạch ở đây!
EKons

Chà, ?[là các toán tử toàn cầu, nhưng không đặc biệt trong tất cả các bối cảnh, nhưng *dường như là vậy, vì thực sự echo *rất tệ echonội dung của thư mục hiện tại (không thoát khỏi bất cứ điều gì). echo ?vang một nghĩa đen ?echo [vang một nghĩa đen [. Ngoài ra, ]là một oberator toàn cầu quá.
EKons

1
@ ΈρκΚω, *khi một quả cầu mở rộng ra tất cả các tệp ?không bị ẩn, [a-z]thành các tệp một ký tự không bị ẩn, thành các tệp có tên là một ký tự đơn giữa a và z, v.v. Khi chúng không khớp với bất kỳ tệp nào (như trong trường hợp của bạn ?), tùy thuộc vào trình bao, bạn sẽ gặp lỗi không khớp hoặc mẫu mở rộng sang chính nó. Trong mọi trường hợp, ngay cả trên shell nơi chúng mở rộng sang chính chúng, chúng cần được trích dẫn trong trường hợp chúng có thể khớp với một tệp.
Stéphane Chazelas

Nhưng, không phải là một quả địa cầu, *vẫn mở rộng đến một cái gì đó.
EKons

@ ΈρκΚω, *giống như ?, nếu nó không khớp (đối với trường hợp *một mình, đó là khi chỉ có các tệp bị ẩn trong thư mục hiện tại, vì a*ở đó không có tệp nào có tên bắt đầu bằng a...), nó sẽ mở rộng thành bản thân (nhất Bourne giống như vỏ), hoặc đặt ra một lỗi không phù hợp ( csh, tcsh, fish(cảnh báo), zsh, bash -O failglob, đầu vỏ Unix), (hoặc mở rộng để không có gì với các tùy chọn nullglob của một số vỏ hoặc nếu có mô hình khác mà mở rộng để một cái gì đó trong csh, tcsh, zsh -o cshnullglob, vỏ unix sớm).
Stéphane Chazelas 16/07/2016

4

1. Thoát

Thoát tất cả các ký tự này bằng một \, như thế này (không hoạt động trên dòng mới / trả về vận chuyển):

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

2. Báo giá kép

Gửi kèm toàn bộ văn bản bằng "s, như thế này:

$ 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. Trích dẫn đơn

Tương tự như trích dẫn kép, nhưng không có mã thông báo đặc biệt.

$ proof=proveit;echo 'This should not read "proveit": $proof'
This should not read "proveit": $proof

1
Bạn đang mô tả hành vi của fishshell chứ không phải shell giống Bourne trong đó trích dẫn duy nhất trích dẫn mỗi ký tự (dấu gạch chéo ngược không đặc biệt trong '...'). Lưu ý rằng trong fish, %cũng là một nhân vật đặc biệt.
Stéphane Chazelas

@ StéphaneChazelas Tôi không biết làm thế nào fishhoạt động, nhưng kinh nghiệm của tôi là, trong sh, echo '\\'tiếng vang \ echo '\''tiếng vang '.
EKons

1
echo '\\'đầu ra \ bởi vì bạn echomở rộng các chuỗi thoát ANSI C (một số echotriển khai cần echo -e '\\'cho việc đó). printf '%s\n' '\\'đầu ra \\.
Stéphane Chazelas

Lưu ý rằng shkhông xác định một vỏ cụ thể, có và đã có rất nhiều vỏ khác nhau và thường không tương thích được gọi sh.
Stéphane Chazelas

@ StéphaneChazelas Oh được rồi, tôi sẽ thay đổi điều đó ngay bây giờ. Nhân tiện, có phải là \'một mã thông báo đặc biệt trong một chuỗi ký tự được trích dẫn không?
EKons
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.