标签: syntax

使用 `$var && action` 将空变量视为逻辑“true”(shell 解析)

考虑一种简单的调试风格,其中$debug可以设置为truefalse根据某些命令行标志:

\n
$debug && echo "Something strange just happened" >&2\n
Run Code Online (Sandbox Code Playgroud)\n

我知道有更好的方法来防止值设置,例如${debug:-false}甚至是全功能的logMessage()-type 函数,但让我们暂时搁置它。

\n

假设仍然未设置或为空的糟糕情况$debug。我预计$debug && echo \xe2\x80\xa6这样的空值$debug将被解析并计算为&& echo \xe2\x80\xa6,这将触发随后的语法错误。但相反,它似乎被评估为类似的东西: && echo \xe2\x80\xa6,最终执行echo.

\n

我已经用bashksh和进行了测试dash,并且场景保持一致。

\n

我的理解是这两行被解析为等价的,但显然它们不是:

\n
unset debug; $debug && echo stuff\nunset debug; && echo stuff\n
Run Code Online (Sandbox Code Playgroud)\n

为什么代码会表现得好像未设置的变量在逻辑上为真,而不是因诸如 之类的错误而失败syntax error near unexpected token `&&'

\n

shell syntax

13
推荐指数
3
解决办法
1021
查看次数

太多的shebang(脚本声明)行——有什么办法可以减少它们的数量?

我有一个由大约 20 个小.sh文件组成的项目。我将这些命名为“小”是因为一般来说,没有文件超过 20 行代码。我采用了模块化方法,因为这样我忠于Unix 哲学,而且对我来说维护项目更容易。

在每个.sh文件的开头,我把#!/bin/bash.

简单地说,我理解脚本声明有两个目的:

  1. 它们帮助用户回忆执行文件所需的外壳程序(例如,几年后没有使用该文件)。
  2. 它们确保脚本仅使用特定的 shell(在这种情况下为 Bash)运行,以防止在使用另一个 shell 时出现意外行为。

当一个项目开始从 5 个文件增长到 20 个文件或从 20 个文件增长到 50 个文件时(不是这种情况,只是为了演示)我们有 20 行或 50脚本声明。我承认,尽管对某些人来说可能很有趣,但使用 20 或 50 个而不是每个项目仅使用1 个(可能在项目主文件中)对我来说感觉有点多余。

有没有办法通过在某个主文件中使用一些“全局”脚本声明来避免这种所谓的 20 或 50 行或更多行的脚本声明冗余?

shell-script shebang syntax

12
推荐指数
4
解决办法
1841
查看次数

如何在 Bash 中导出大量变量?

我使用 Bash 4.3.48(1) 并且.sh在 shebang 下有一个包含大约 20 个变量的文件。该文件仅包含变量。

这是模式:

x="1"
y="2"
...
Run Code Online (Sandbox Code Playgroud)

我需要以DRY方式导出所有这些变量:例如,一个export对所有变量,而不是说 20export对 20 个变量。

该文件中执行此操作的最优雅方式(最短、最有效)是什么?

一个for循环?一个array?也许比这些更简单(某种集合糖语法)?

environment-variables variable syntax

12
推荐指数
1
解决办法
4740
查看次数

为什么大括号命令组在 POSIX Shell 语法中的左大括号后需要空格?

TL;DR:为什么 POSIX 括号组在{保留字后需要空格,而子外壳在保留字后不需要(

POSIX shell 语法定义花括号组和子shell如下

brace_group      : Lbrace compound_list Rbrace

subshell         : '(' compound_list ')'
Run Code Online (Sandbox Code Playgroud)

现在,如果我们从字面上看,空格很重要。这意味着必须有空间描述开始和结束括号和括号,如

{ echo hello world; }

( echo hello world )
Run Code Online (Sandbox Code Playgroud)

这也符合复合命令定义

这些复合命令中的每一个在开头都有一个保留字或控制运算符,并在末尾有一个相应的终止符保留字或运算符。

然而,没有意义的是为什么(list)并且( list )工作得很好((不需要后面的空格),但是大括号扩展必须有一个前导空格,即{echo hello;}不起作用。

当然,保留字被视为 shell 字是有意义的,之后需要一个空格来与字段拆分的概念保持一致,但是定义本身并没有提到空格。此外,如果{(都被复合命令的 POSIX 定义视为保留字,为什么在这些保留字之后的空格字符方面对它们的处理方式不同?现在,ksh(1)手册确实说明:

作为字符序列的单词由不带引号的空白字符(空格、制表符和换行符)或元字符(<、>、|、;、&、(和))分隔

换句话说,它是有道理的ksh的将认识到(作为字符,其中第一字将是一个命令或变量赋值。POSIX,但是似乎没有提到(作为元字符。就 POSIX 语法而言,我发现的唯一可能的解释是它{被认为是一个“标记”,而 as(没有被列为一个。

/* These are reserved words, not …
Run Code Online (Sandbox Code Playgroud)

shell posix subshell syntax

12
推荐指数
2
解决办法
747
查看次数

!!: 在 bash 中是什么意思?

观看视频(https://vimeo.com/56166857 & https://www.youtube.com/watch?v=9CTfGS0gEOk @ 1m:34s),主持人(TJ Holowaychuk)写道:

touch !!:2{...}
Run Code Online (Sandbox Code Playgroud)

!!:2在任何地方都找不到什么意思。

我得到(重复上一个命令)!!但是,的含义

!!:2
Run Code Online (Sandbox Code Playgroud)

我不知道,找不到答案,这里的搜索没有返回任何结果,所以......我被卡住了。

语境:

为了一次创建多个目录,他写道:

mkdir -p lib/{login,signup,users,posts}
Run Code Online (Sandbox Code Playgroud)

为了在每个目录中创建相同的文件,他写道:

touch !!:2/{package.json,index.json}
Run Code Online (Sandbox Code Playgroud)

输出是:

touch lib/{login,signup,users,posts}/{package.json,index.json}
Run Code Online (Sandbox Code Playgroud)

结果是:

这两个文件是在每个目录中创建的。

bash touch syntax

11
推荐指数
1
解决办法
1881
查看次数

为什么不能反转 while 循环的输入重定向运算符的顺序?

在 Bash 中,您可以将输入重定向操作符移到命令的前面:

cat <<< "hello"
# equivalent to
<<< "hello" cat
Run Code Online (Sandbox Code Playgroud)

为什么你不能对 while 循环做同样的事情?

while read -r line; do echo "$line"; done <<< "hello"
# hello

<<< "hello" while read -r line; do echo "$line"; done
# -bash: syntax error near unexpected token `do'
Run Code Online (Sandbox Code Playgroud)

我觉得这有点令人困惑,因为您可以通过管道进入 while 循环。我做错了什么还是只是一个设计决定?

bash io-redirection syntax

11
推荐指数
1
解决办法
699
查看次数

/RE/ 与 awk 中的“RE”

在 中,和函数awk的第一个参数、函数的第二个参数以及, 的可选第三个参数是扩展正则表达式。sub()gsub()match()split()

这样的参数可以是任意表达式,其计算结果为被解释为正则表达式的字符串,也可以是正则表达式常量。

在 中,为某些正则表达式(语法中的“标记”)awk编写了正则表达式常量。/RE/REEREawk

问题:假设RE保持不变(一些非变量正则表达式),在调用中使用/RE/和使用"RE"(语法STRING中的“标记” )之间是否有任何实际差异?或者:是否有任何已知的实现可以在调用上述函数时区分这两种表示正则表达式的方式?awksub()awk

询问的原因是我记得必须修改一些尝试在调用or中awk用作正则表达式的代码,因为无论出于何种原因,除非我使用 调用该函数,否则手头的实现会做错事情。"RE"sub()gsub()awk/RE/

不幸的是,这是不久前(2年多)的事了,所以我不记得细节了,我什至不确定我当时使用的是什么Unix(可能是OpenBSD),但从那时起我就一直想问这个问题。

awk regular-expression syntax

9
推荐指数
1
解决办法
530
查看次数

什么时候使用“grep -- SOMEPATTERN”有用?

在 Linux/AIX 下,什么时候使用 有用--,如以下命令:

grep -- SOMEPATTERN
Run Code Online (Sandbox Code Playgroud)

command-line syntax

8
推荐指数
2
解决办法
553
查看次数

回勾与双引号

这个问题想了很久,还是不知道怎么查

这是:

x=`command -v r2g`
Run Code Online (Sandbox Code Playgroud)

与此相同:

x="$(command -v r2g)"
Run Code Online (Sandbox Code Playgroud)

还是和这个一样:

x=$(command -v r2g)
Run Code Online (Sandbox Code Playgroud)

...如果是后者,我应该这样做来修复它吗?

x="`command -v r2g`"
Run Code Online (Sandbox Code Playgroud)

shell-script syntax

8
推荐指数
1
解决办法
2740
查看次数

如何在匹配表达式中编写正则表达式文字?

这个问题是关于在 bash 下的匹配表达式中编写正则表达式文字的正确方法。

在 zsh 中,下面的匹配成功了,正如我所料:

% [[ ' 123 ' =~ '^ [0-9]+ $' ]]; echo $?
0
Run Code Online (Sandbox Code Playgroud)

在 bash 中并非如此:

$ [[ ' 123 ' =~ '^ [0-9]+ $' ]]; echo $?
1
Run Code Online (Sandbox Code Playgroud)

我知道这场比赛在 bash 中成功

$ ( regexp='^ [0-9]+ $'; [[ ' 123 ' =~ $regexp ]]; echo $? )
0
Run Code Online (Sandbox Code Playgroud)

...但它需要将正则表达式分配给一个中间变量。


我的问题是:如何在 bash 下的匹配表达式中编写任意正则表达式文字

scripting bash shell-script regular-expression syntax

6
推荐指数
2
解决办法
2081
查看次数