![在 bash 中转义](https://linux22.com/image/86902/%E5%9C%A8%20bash%20%E4%B8%AD%E8%BD%AC%E4%B9%89.png)
给定一条文本消息,我需要以编程方式生成一个 bash 命令来打开终端模拟器并在其中显示此文本。
例如,对于HelloWorld
输入字符串,我需要返回以下输出字符串:
gnome-terminal -e "$SHELL -c echo\ HelloWorld;exec\ $SHELL"
问题是我的输入消息可能包含任意符号。
通过反复试验,我确定不同的符号需要转义不同的次数:
"A" must be converted to "A" (0 times to be escaped)
" " must be converted to "\ " (1 times to be escaped)
"(" must be converted to "\\\(" (2 times to be escaped)
"\" must be converted to "\\\\\\\\" (3 times to be escaped)
例如,\(o o)/
必须在命令中插入为\\\\\\\\\\\(o\ o\\\)\\\/
:
gnome-terminal -e "$SHELL -c echo\ \\\\\\\\\\\(o\ o\\\)\\\/;exec\ $SHELL"
事实上,我根本不懂bash,所以我不完全理解其背后的逻辑。
您能否告诉我一般规则:如何转换 ASCII 子集 (10,32-126) 中的任何符号?
编辑:
让我更清楚地了解我正在做的事情。
我正在尝试编写一个函数(用某种编程语言)来接收字符串 InputText 并返回另一个字符串,这是一个正确的 bash 命令。
目前,我正在尝试将此函数实现为以下简单串联:
1)常量前缀gnome-terminal -e "$SHELL -c echo
2)依赖于InputText的内部部分
3)常量后缀;exec\ $SHELL"
问题出在内部部分。我试图将其计算为转换后的每个 InputText 符号的串联。但我不知道如何转换任意符号。
编辑2:
感谢 choroba 提出使用单引号来避免大规模转义的想法。
我学到了很多关于 bash 的知识。 ))
这是 choroba 答案的修改版本。
同样的想法,但没有“反斜杠反斜杠串联”,在 Lua 中实现:
function run_terminal(text)
local function q(s) return "'"..s:gsub("'","'\\''").."'" end
os.execute(
'gnome-terminal -e "$SHELL -c "'..q(q("echo "..q(text)..";exec $SHELL"))
)
end
run_terminal "Some Text"
编辑3:
感谢 Gilles 提到 gnome-terminal 的“-x COMMAND”选项。此选项不需要引用,因此我们可以减少生成命令中的引用级别:
function run_terminal(text)
local function q(s) return "'"..s:gsub("'","'\\''").."'" end
os.execute("gnome-terminal -x sh -c "..q("echo "..q(text)..";exec $SHELL"))
end
run_terminal "Some Text"
答案1
引用该字符串,您只需要用反斜杠引号即可。如果引用两次,则需要转义两种引用类型。
更新:Gnome 终端需要三重引号。只需在字符串中转义单引号两次,并在插入的字符串周围使用带引号的单引号即可。您还需要对原始字符串中的反斜杠进行反斜杠。
证明:我使用了以下 Perl 脚本:
#!/usr/bin/perl
use strict;
use warnings;
use feature qw{ say };
chomp( my $msg = <> );
$msg =~ s/\\/\\\\/g; # Quis backslashies backslashes tandem?
$msg =~ s/'/'\\''/g for 1, 2; # Replace ' by '\'' twice.
$msg =~ s/"/\\"/g; # Backslash double quotes.
system q(gnome-terminal -e 'bash -c "echo '\\'') . $msg . q('\\''; exec bash"');
答案2
忘记引用并将文本放入环境变量中。
用于-x
启动 shell。
不要为 编写代码$SHELL
:你不知道它能理解什么语法。运行 中的代码sh
,并调用$SHELL
以调用交互式 shell。
message='HelloWorld' gnome-terminal -x sh -c 'printf %s\\n "$message"; unset message; exec "$SHELL"'