Điều trị dấu gạch chéo ngược trên vỏ


9

Làm thế nào để echoprintfbackslashes món đặc sản ở zsh, bashvà vỏ khác?

Theo zsh tôi nhận được các hành vi sau:

$ echo "foo\bar\baz"
foaaz
$ echo "foo\\bar\\baz"
foaaz
$ echo 'foo\bar\baz'
foaaz
$ echo 'foo\\bar\\baz'
foo\bar\baz

Trong bash , mọi thứ có vẻ phù hợp hơn một chút:

bash$ echo "foo\bar\baz"
foo\bar\baz
bash$ echo 'foo\bar\baz'
foo\bar\baz
bash$

Nhưng cụ thể hơn: Làm thế nào tôi có thể vượt qua một chuỗi chứa dấu gạch chéo ngược như\\foo\bar\something :

  • echo
  • printf
  • print

và nhận được chính xác cùng một chuỗi? (trong zshbash)?

Đây là một thử nghiệm khác với các chức năng trong zsh:

function foo
{
    echo -E '$1'
}

$ foo \\here\is\some\path
$1

Làm thế nào tôi có thể có nó chỉ in \\here\is\some\path?

Cập nhật (Lưu ý: điều này hiện đã được trả lời trong bình luận của Stephane)

Tôi đã thử như sau trong zsh 5.0.2:

function foo
{
    printf '$s\n' $1 
}

foo '\\some\path'

Nhưng bản in này $s?


3
Sử dụng printf, echokhông phải là di động trong vấn đề này.
jordanm

hàm "foo" của bạn: thay thế 'bằng "và gọi nó bằng: foo '\\ here \ is \ some \ path' (nếu không, shell invoke có cơ hội diễn giải '\' trước khi chúng vào hàm)
Olivier Dulac

2
Chức năng của bạn được sử dụng '$s\n'khi cần sử dụng '%s\n'.
cjm

Câu trả lời:


12

zsh echohành xử theo cách tiêu chuẩn, giống như bashtrong chế độ UNIX. Đó là nó mở rộng \bsang ký tự BS ASCII như đặc tả UNIX yêu cầu.

Không sử dụng echođể hiển thị các chuỗi tùy ý, sử dụngprintf :

printf '%s\n' "$1"

print -r -- "$1"cũng hoạt động nhưng là ksh/ zshcụ thể.

echo -E - "$1"làm việc với zshvà tôi tin rằng một số BSD.

cat << EOF
$1
EOF

hoạt động trong bất kỳ lớp vỏ nào giống Bourne, ngay cả những lớp từ vài thập kỷ khi không có printflệnh nhưng nó sinh ra một quy trình mới, và ngày nay thực sự không cần thiết vì chúng ta có printfở khắp mọi nơi.

Và nhân tiện, bạn cần thoát dấu gạch chéo ngược trên dòng lệnh shell vì nó đặc biệt đối với shell (mọi shell nhưng rc), vì vậy:

$ foo '\\foo\bar'

foo \\foo\barsẽ chuyển "\foo\bar"chuỗi foomà không thể phát minh lại dấu gạch chéo ngược bị mất.


Cảm ơn Stephane. Thật kỳ lạ, công printf '%s\n' "$var"trình xây dựng cho tôi trên dòng lệnh ( zsh 5.0.2tức là mới nhất), nhưng không nằm trong một chức năng (xem bản cập nhật của tôi trong OP). Tại sao?
Amelio Vazquez-Reina

1
Đó là printf '%s\n', không phải printf '$s\n'bạn muốn. Lưu ý rằng bạn cần trích dẫn các biến trong các shell khác ngoài zsh( "$1", không phải $1) và cú pháp định nghĩa hàm tiêu chuẩn là foo() { ...; }, mặc dù bất kỳ shell nào cũng bashcho phép foo() any-commandfunction foo { .... }kshcú pháp.
Stéphane Chazelas

@Marcus, đó là một câu trả lời cho một câu hỏi khác.
Stéphane Chazelas

1

câu trả lời mới: đọc -r var

-r  raw input - disables interpretion of backslash escapes and line-continuation in the read data

và để hiển thị:

printf "%s" "$var"
echo "$var"

nên làm việc.

Vì vậy, cho chức năng foo của bạn:

function foo
{
    read -r var
    echo -E "var is : ${var}"
}

$ foo 
\\here\is\some\path
var is : \\here\is\some\path

câu trả lời cũ bên dưới (không trả lời, nhưng có thể hữu ích ^^)

chỉ thay thế mỗi \bằng \\để nói với vỏ "mà nó là một literall \tôi muốn". mặt khác (ví dụ trong zsh, trong ví dụ của bạn) nó cũng có thể \bcó nghĩa là "1 backspace", hoặc bất cứ điều gì.

ví dụ bạn có thể sử dụng sed:

sed -e 's,\\,\\\\,g' < the_original > the_escaped_backslaches_version

(xem làm thế nào bạn cũng cần phải thoát "\" ở đó, để nói với sed điều tương tự: "đó là một chữ" hầu hết cũng vậy)


Cảm ơn nhưng như tôi đã đề cập trong tiêu đề: Tôi muốn tránh thoát khỏi dấu gạch chéo ngược.
Amelio Vazquez-Reina

Rất tiếc, tôi sẽ chỉnh sửa ^^
Olivier Dulac

Cảm ơn! Nhưng read -r vardường như chờ đợi đầu vào từ STDIN. Điều gì xảy ra nếu tôi vượt qua nó như là một đối số? (ví dụ: foo \\here\is\some\path)
Amelio Vazquez-Reina

shell IS diễn giải dấu gạch chéo ngược. Đó là lý do tại sao bạn có thể nên chuyển đối số chuyển sang đọc, xem ví dụ "foo" của tôi.
Olivier Dulac

1
iow: bạn muốn xử lý chuỗi "không chuẩn" bằng shell: bạn có thể dễ dàng hơn (và mở rộng hơn) để chương trình của bạn tuân thủ những gì bạn muốn, thay vì cố gắng có chương trình shell-invoke-that-chương trình cư xử như bạn muốn Vì vậy: vượt qua các đối số (những đối tượng có chứa "\" mà bạn không muốn thoát) sau khi chương trình được bắt đầu, thông qua "read -r", và không phải trên dòng lệnh shell của nó.
Olivier Dulac

1

Nói chung, bạn không thể, bởi vì dấu gạch chéo ngược ký tự thoát (và như vậy phải được thoát khi giá trị theo nghĩa đen của nó là bắt buộc). BASH cung cấp các trích dẫn đơn cho mục đích này, tuy nhiên bạn không thể sử dụng thoát một trích dẫn trong một chuỗi trích dẫn.

Đối với echosự khác biệt, nó là một tích hợp có thể hoạt động khác nhau trên các vỏ (ở một mức độ nào đó). Ví dụ, BASH tích hợp sẵn có một -etùy chọn cho biết nó diễn giải các chuỗi dấu gạch chéo ngược - với nó, bạn sẽ có được hành vi mà bạn đã thấy trong trình bao Z.

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.