跨壳反斜杠的处理


9

如何echoprintf在治疗反斜杠zshbash和其他贝壳?

zsh下,我得到以下行为:

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

bash下,情况似乎更加一致:

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

但更具体而言:如何传递包含反斜杠的字符串,例如\\foo\bar\something

  • echo
  • printf
  • print

并获得完全相同的字符串?(在zsh和中bash)?

这是另一个在zsh中使用函数的实验:

function foo
{
    echo -E '$1'
}

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

我怎样才能只打印它\\here\is\some\path

更新(注意:这已在Stephane的评论中得到回答)

我在zsh 5.0.2中尝试了以下方法:

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

foo '\\some\path'

但这印$s吗?


3
使用printfecho就此而言不可移植。
约旦

您的“ foo”函数:替换'",然后用foo'\\ here \ is \ some \ path'调用它(否则,调用shell在获得该函数之前有机会解释“ \”)
Olivier Dulac

2
您的函数'$s\n'在应该使用的时候使用过'%s\n'
cjm

Answers:


12

zsh echo遵循标准方式,例如bash在UNIX模式下。就是说,它扩展\b为UNIX规范要求的ASCII BS字符。

不要使用echo显示任意字符串,请使用printf

printf '%s\n' "$1"

print -r -- "$1"也适用,但ksh/ zsh具体。

echo -E - "$1"zsh我合作,我相信一些BSD。

cat << EOF
$1
EOF

可以在任何类似Bourne的shell中运行,甚至是几十年来没有printf命令但可以产生新进程的shell ,它实际上不再是必需的,因为如今我们printf无处不在。

顺便说一句,您需要在shell命令行上转义反斜杠,因为它对shell来说是特殊的(每个shell rc除外),因此:

$ foo '\\foo\bar'

foo \\foo\bar会将无法重新创建丢失的反斜杠的"\foo\bar"字符串传递foo回去。


谢谢斯蒂芬。奇怪的是,这种构造printf '%s\n' "$var"在命令行(zsh 5.0.2即最新版本)上对我有效,但在函数内部却无效(请参见OP中的更新)。为什么?
阿梅利奥·瓦兹奎兹·雷纳

1
printf '%s\n',不是printf '$s\n'您想要的。请注意,您需要引用变量其他外壳比zsh"$1"$1)和标准函数定义的语法foo() { ...; },但任何外壳,但bash允许foo() any-command,并且function foo { .... }ksh语法。
斯特凡Chazelas

@Marcus,这是对另一个问题的答案。
斯特凡Chazelas

1

新答案:读取-r var

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

并显示:

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

应该管用。

因此,对于您的foo函数:

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

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

下面的旧答案(未回答,但可能有用^^)

只需更换每个\通过\\告诉壳“它一literall \我想要的”。否则(例如,在您的示例中的zsh中)很可能\b意味着“ 1退格键”或其他内容。

例如,您可以使用sed:

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

(请参阅您还需要如何在其中转义“ \”,以告诉sed相同的内容:“这是我想要的字面量“ \”)(请注意,我用''而不是'“包围了它,以避免shell解释大部分也是)


谢谢,但是正如我在标题中所述:我想避免转义反斜杠。
2013年

糟糕,我将编辑^^
Olivier Dulac

谢谢!但read -r var似乎要等待来自的输入 STDIN。如果我将其作为参数传递怎么办?(例如foo \\here\is\some\path
阿梅里奥·瓦兹奎兹·雷纳

shell在解释反斜杠。这就是为什么您应该将传递给read的参数移动的原因,请参见我的“ foo”示例。
Olivier Dulac

1
iow:您希望由shell对字符串进行“非标准”处理:您可以更轻松(更广泛地)使您的程序符合您的要求,而不必尝试让shell调用该程序来表现得像你想要的。因此:在程序启动后,通过“ read -r”传递args(包含您不想转义的“ \”的args),而不是在其调用shell命令行上传递。
Olivier Dulac 2013年

1

一般来说,您不能这样做,因为反斜杠转义字符(因此,在需要其字面值时必须转义)。BASH为此提供了单引号,但是您不能在单引号字符串中使用转义单引号。

至于echo差异,它是一个内置的,可能在各个shell上表现不同(在某种程度上)。例如,内置的BASH有一个-e选项,告诉它解释反斜杠序列-有了它,您将获得在Z shell中看到的行为。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.