简体   繁体   English

将转义符添加到字符串中的特殊字符(作为函数)

[英]Add escapes to special characters in a string (as a function)

So I what I am looking to find working is something like this: 所以我要寻找的工作是这样的:

$ echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\?
This is a special character string. \~`!@#$%^&*()-=+[]{}|;:'",<>/?

I want to be able to add backslashes to only the special characters. 我希望能够仅对特殊字符添加反斜杠。 I have seen examples around here that do indeed work, however I can't seem to get them working as a pipable function. 我在这里看到了确实有效的示例,但是我似乎无法使它们作为可点入功能发挥作用。

Here's what I would like to have it look like: 这是我想要的样子:

$ echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\? | addESC
This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\?

$ echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\? | addESC | addESC
This\\\ is\\\ a\\\ special\\\ character\\\ string.\\\ \\\\\\~\\\`\\\!\\\@\\\#\\\$\\\%\\\^\\\&\\\*\\\(\\\)\\\-\\\=\\\+\\\[\\\]\\\{\\\}\\\|\\\;\\\:\\\'\\\"\\\,\\\<\\\>\\\/\\\?

Using bash on High Sierra. 在High Sierra上使用bash。

Edit as per Andreas' request 根据Andreas的要求进行编辑

Example of escaping characters I've used that I confirm to work, just not in a function: https://unix.stackexchange.com/questions/141312/how-to-escape-special-characters-in-a-string 我使用的转义字符示例已确认可以正常工作,只是不在函数中起作用: https : //unix.stackexchange.com/questions/141312/how-to-escape-special-characters-in-a-string

I have tried: 我努力了:

$ echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\? | printf '%q\n'

$ printf '%q\n' <<< printf '%q\n' <<< echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\?

$ echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\? | xargs printf '%q\n'

Before I attempt to answer, I have a some warnings. 在尝试回答之前,我有一些警告。 I'm not sure what the actual goal is here, so depending on what that is, there are several potential problems. 我不确定此处的实际目标是什么,因此根据具体情况,有几个潜在的问题。

First, it's impossible in general to reconstruct how a string was quoted/escaped on the command line, because there are many different ways to express the same string in shell syntax. 首先,通常无法重构在命令行上如何对字符串加引号/转义,因为在shell语法中有许多不同的方式来表达相同的字符串。 For example, all of the following commands pass exactly the same argument to echo , and therefore print exactly the same thing: 例如,以下所有命令将完全相同的参数传递给echo ,因此打印完全相同的内容:

echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\?
echo This\ is\ a\ special\ character\ string.\ \\~\`\!@#\$%^\&*\(\)-=+[]{}\|\;:\'\",\<\>/?
echo 'This is a special character string. \~`!@#$%^&*()-=+[]{}|;:'"'"'",<>/?'
echo $'This is a special character string. \~`!@#$%^&*()-=+[]{}|;:\'",<>/?'
...and many more

(Note: technically, the second of those might pass something different, if the current directory happens to contain one or more files with specific really weird names.) (注意:从技术上讲,如果当前目录恰好包含一个或多个具有特定真正奇怪名称的文件,则第二个可能传递不同的内容。)

Second, some versions of echo do some additional escape processing. 其次,某些版本的echo执行一些附加的转义处理。 Some do this only when passed the -e option. 有些仅在通过-e选项时才执行此操作。 Some print "-e" if you try to pass the -e option. 如果尝试传递-e选项,则打印一些“ -e”。 It's a mess. 一团糟。

Third, what needs to be escaped and how really depends on what you're going to use it for (and specifically, how it's going to be parsed). 第三,需要逃避什么以及如何逃避取决于您将使用它的目的(尤其是如何解析)。 Different situations involve different parsing rules, and you have to add escapes appropriate for the specific processing that the output is going to be subject to. 不同的情况涉及不同的解析规则,并且您必须添加适合输出将要经受的特定处理的转义符。 In my answer, I concentrated on reversing the specific escaping in your example. 在我的回答中,我专注于反转示例中的特定转义。

My solution: you can use sed in a pipeline to add escapes before any of a list of characters, specified as a bracket expression. 我的解决方案:您可以在管道中使用sed在指定为方括号表达式的任何字符列表之前添加转义符。 It's slightly tricky because "]" and "-" are delimiters in a bracket expression; 这有点棘手,因为“]”和“-”是方括号表达式中的定界符; the trick there is to specify "]" as the first character and "-" as the last, so they're not mistaken for their other meanings. 诀窍是将“]”指定为第一个字符,将“-”指定为最后一个字符,因此不要将它们误认为其他含义。 Also, I'm going to write this as a single-quoted string, so the single-quote requires special handing. 另外,我将其编写为单引号字符串,因此单引号需要特殊处理。 Like this: 像这样:

sed 's/[][ \~`!@#$%^&*()=+{}|;:'"'"'",<>/?-]/\\&/g'

Or as a function: 或作为功能:

addESC() { sed 's/[][ \~`!@#$%^&*()=+{}|;:'"'"'",<>/?-]/\\&/g'; }

Example: 例:

$ echo This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\? | addESC 
This\ is\ a\ special\ character\ string.\ \\\~\`\!\@\#\$\%\^\&\*\(\)\-\=\+\[\]\{\}\|\;\:\'\"\,\<\>\/\?

As for why your attempts didn't work: In the first, printf doesn't read from stdin, it expects arguments. 至于为什么您的尝试不起作用的原因:首先, printf不从stdin读取,它需要参数。 The third tries to fix this with xargs , but xargs does its own quote/escape parsing and removal, which messes it up. 第三个尝试使用xargs修复此问题,但xargs了自己的引用/转义分析和删除,将其弄乱了。 In the second, <<< takes a string , not a command ; 在第二个中, <<<接受字符串 ,而不是命令 to apply it to the output of a command, you'd use something like <<< "$(command)" . 要将其应用于命令的输出,可以使用<<< "$(command)" Also, in all versions, bash printf's %q quotes and/or escapes specifically as needed for consumption by bash itself, which doesn't match the escaping in your example. 同样,在所有版本中,bash printf的%q引号和/或转义都是bash本身根据需要使用的,这与示例中的转义符不匹配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM