在 bash 中转义

在 bash 中转义

给定一条文本消息,我需要以编程方式生成一个 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"'

相关内容