强制在反引号中进行大括号扩展或者为什么这不一致?
forcing brace expansion in backticks or why is this inconsistent?
当使用反引号(在 perl 中)时,我似乎与大括号扩展有些不一致
print `ls -d ~/{a,b}`;
工作正常,但是当我尝试
print `ls -d ~/{a}`;
我得到:
ls: cannot access /home/user/{a}: No such file or directory
我尝试了各种引用、间距和转义,但都无济于事。我的问题是,有没有办法强制扩展?我意识到如果我自己把这些东西弄混的话我可以一起避免这个问题,但我对这种行为很好奇
我在 bash 和 tcsh 下都试过了。在 tcsh 下直接使用时,该命令有效,但在 bash 下它不会
现在,经过您的多次编辑,我了解到您可能使用了两种不同的 shell。而且,调用 shell 的是 perl,不是你。
所以,覆盖三个要素:
bash
在bash。一个简单的{a}不会展开:
$ echo ~/{a,b}
/home/user/a /home/user/b
$ echo ~/{a}
/home/user/{a}
ls
将其作为文件进行搜索,但未找到。
手册 man bash 的相关部分是(强调我的):
A correctly-formed brace expansion must contain unquoted opening and closing braces, and at least one unquoted comma or a valid sequence expression.
{a}
缺少必需的逗号。
唯一的选择是实际使用
$ print `ls -d ~/a`
tcsh
在tcsh
中:一个简单的{a}将被扩展(如在csh
shell中):
使用 >
作为 tcsh 提示的 shell 指标:
> echo --{a,b}++
--a++ --b++
> echo --{a}++
--a++
作为一个简单的 {}
也将:
$ echo --{}++
--++
唯一 不会 删除的大括号是 {}
和 {
以及 }
。
IIF(当且仅当)它们被识别为 "words"。最常被空格包围:
$ echo --{}++ == {} .. { :: } aa { bb
--++ == {} .. { :: } aa { bb
如果 {
或 }
显示为单词的 部分 ,没有匹配的大括号,则为错误:
> echo aa{bb
Missing '}'.
man tcsh上唯一的描述是很短(不清楚?):
> As a special case the words `{', `}' and `{}' are passed undisturbed.
perl
如果 shell 命令是 called from perl,在调用 shell 的情况下,比如在 Unix 系统下,调用的 shell 是 /bin/sh
.
一个额外的变化,/bin/sh
在大多数 linux 系统中由 bash 服务,由 tcsh in FreeBSD and by ksh or csh in OpenBSD。
很难预测名为 /bin/sh
的 perl 的输出。
您可以确保调用特定的 shell:
#!/usr/bin/perl
print `/bin/tcsh -c 'ls -d ~/{a,b}'`;
现在问题仍然存在:
- 为什么需要对单个字符使用大括号扩展?
当您在使用 shell 命令时遇到问题,请在 Perl(或任何程序)之外尝试它们以查看它们的作用:
Bash:
$ ls ~/{a}
ls: /Users/brian/{a}: No such file or directory
$ ls ~/{a,b}
ls: /Users/brian/a: No such file or directory
ls: /Users/brian/b: No such file or directory
切:
% ls ~/{a}
ls: /Users/brian/a: No such file or directory
% ls ~/{a,b}
ls: /Users/brian/a: No such file or directory
ls: /Users/brian/b: No such file or directory
因此,您会看到两个 shell 以不同方式扩展 glob。来自 bash docs:
A correctly-formed brace expansion must contain unquoted opening and closing braces, and at least one unquoted comma or a valid sequence expression. Any incorrectly formed brace expansion is left unchanged.
来自 tcsh docs 有点欠缺,因为它没有提到您不需要逗号进行扩展:
The metanotation 'a{b,c,d}e' is a shorthand for 'abe ace ade'. Left-to-right order is preserved: '/usr/source/s1/{oldls,ls}.c' expands to '/usr/source/s1/oldls.c /usr/source/s1/ls.c'. The results of matches are sorted separately at a low level to preserve this order: '../{memo,*box}' might expand to '../memo ../box ../mbox'. (Note that 'memo' was not sorted with the results of matching '*box'.) It is not an error when this construct expands to files which do not exist, but it is possible to get an error from a command to which the expanded list is passed. This construct may be nested. As a special case the words '{', '}' and '{}' are passed undisturbed.
现在,在 Perl 中,反引号使用 /bin/sh。当您启动 perl 进程时,它并不关心您在哪个 shell 中。来自 perlop:
A string which is (possibly) interpolated and then executed as a system command with /bin/sh or its equivalent.
这就是您看到 bash 行为的原因。但是,您可以使用任何您喜欢的 shell(并且在系统上可用):
my $output = `tcsh -c 'ls -l ~/{a}'`
当使用反引号(在 perl 中)时,我似乎与大括号扩展有些不一致
print `ls -d ~/{a,b}`;
工作正常,但是当我尝试
print `ls -d ~/{a}`;
我得到:
ls: cannot access /home/user/{a}: No such file or directory
我尝试了各种引用、间距和转义,但都无济于事。我的问题是,有没有办法强制扩展?我意识到如果我自己把这些东西弄混的话我可以一起避免这个问题,但我对这种行为很好奇
我在 bash 和 tcsh 下都试过了。在 tcsh 下直接使用时,该命令有效,但在 bash 下它不会
现在,经过您的多次编辑,我了解到您可能使用了两种不同的 shell。而且,调用 shell 的是 perl,不是你。
所以,覆盖三个要素:
bash
在bash。一个简单的{a}不会展开:
$ echo ~/{a,b}
/home/user/a /home/user/b
$ echo ~/{a}
/home/user/{a}
ls
将其作为文件进行搜索,但未找到。
手册 man bash 的相关部分是(强调我的):
A correctly-formed brace expansion must contain unquoted opening and closing braces, and at least one unquoted comma or a valid sequence expression.
{a}
缺少必需的逗号。
唯一的选择是实际使用
$ print `ls -d ~/a`
tcsh
在tcsh
中:一个简单的{a}将被扩展(如在csh
shell中):
使用 >
作为 tcsh 提示的 shell 指标:
> echo --{a,b}++
--a++ --b++
> echo --{a}++
--a++
作为一个简单的 {}
也将:
$ echo --{}++
--++
唯一 不会 删除的大括号是 {}
和 {
以及 }
。
IIF(当且仅当)它们被识别为 "words"。最常被空格包围:
$ echo --{}++ == {} .. { :: } aa { bb
--++ == {} .. { :: } aa { bb
如果 {
或 }
显示为单词的 部分 ,没有匹配的大括号,则为错误:
> echo aa{bb
Missing '}'.
man tcsh上唯一的描述是很短(不清楚?):
> As a special case the words `{', `}' and `{}' are passed undisturbed.
perl
如果 shell 命令是 called from perl,在调用 shell 的情况下,比如在 Unix 系统下,调用的 shell 是 /bin/sh
.
一个额外的变化,/bin/sh
在大多数 linux 系统中由 bash 服务,由 tcsh in FreeBSD and by ksh or csh in OpenBSD。
很难预测名为 /bin/sh
的 perl 的输出。
您可以确保调用特定的 shell:
#!/usr/bin/perl
print `/bin/tcsh -c 'ls -d ~/{a,b}'`;
现在问题仍然存在:
- 为什么需要对单个字符使用大括号扩展?
当您在使用 shell 命令时遇到问题,请在 Perl(或任何程序)之外尝试它们以查看它们的作用:
Bash:
$ ls ~/{a}
ls: /Users/brian/{a}: No such file or directory
$ ls ~/{a,b}
ls: /Users/brian/a: No such file or directory
ls: /Users/brian/b: No such file or directory
切:
% ls ~/{a}
ls: /Users/brian/a: No such file or directory
% ls ~/{a,b}
ls: /Users/brian/a: No such file or directory
ls: /Users/brian/b: No such file or directory
因此,您会看到两个 shell 以不同方式扩展 glob。来自 bash docs:
A correctly-formed brace expansion must contain unquoted opening and closing braces, and at least one unquoted comma or a valid sequence expression. Any incorrectly formed brace expansion is left unchanged.
来自 tcsh docs 有点欠缺,因为它没有提到您不需要逗号进行扩展:
The metanotation 'a{b,c,d}e' is a shorthand for 'abe ace ade'. Left-to-right order is preserved: '/usr/source/s1/{oldls,ls}.c' expands to '/usr/source/s1/oldls.c /usr/source/s1/ls.c'. The results of matches are sorted separately at a low level to preserve this order: '../{memo,*box}' might expand to '../memo ../box ../mbox'. (Note that 'memo' was not sorted with the results of matching '*box'.) It is not an error when this construct expands to files which do not exist, but it is possible to get an error from a command to which the expanded list is passed. This construct may be nested. As a special case the words '{', '}' and '{}' are passed undisturbed.
现在,在 Perl 中,反引号使用 /bin/sh。当您启动 perl 进程时,它并不关心您在哪个 shell 中。来自 perlop:
A string which is (possibly) interpolated and then executed as a system command with /bin/sh or its equivalent.
这就是您看到 bash 行为的原因。但是,您可以使用任何您喜欢的 shell(并且在系统上可用):
my $output = `tcsh -c 'ls -l ~/{a}'`