关于语法:在Bash脚本中进行注释

Commenting in a Bash script

如何从脚本中评论以下几行的每一行?

1
2
3
4
5
6
7
8
9
10
11
12
   cat ${MYSQLDUMP} | \
   sed '1d' | \
   tr",;""
"
| \
   sed -e 's/[asbi]:[0-9]*[:]*//g' -e '/^[{}]/d' -e 's/""//g' -e '/^"{/d' | \
   sed -n -e '/^"/p' -e '/^print_value$/,/^option_id$/p' | \
   sed -e '/^option_id/d' -e '/^print_value/d' -e 's/^"\(.*\)"$/\1/' | \
   tr"
"
"," | \
   sed -e 's/,\([0-9]*-[0-9]*-[0-9]*\)/
\1/g'
-e 's/,$//' | \
   sed -e 's/^/"/g' -e 's/$/"/g' -e 's/,/","/g' >> ${CSV}

如果我尝试添加评论,例如:

1
cat ${MYSQLDUMP} | \ # Output MYSQLDUMP File

我明白了:

1
#: not found

可以在这里发表评论吗?


这将有一些开销,但从技术上讲它确实回答了你的问题:

1
2
3
echo abc `#Put your comment here` \
     def `#Another chance for a comment` \
     xyz, etc.

特别是对于管道,有一个没有开销的清洁解决方案:

1
2
3
4
echo abc |        # Normal comment OK here
     tr a-z A-Z | # Another normal comment OK here
     sort |       # The pipelines are automatically continued
     uniq         # Final comment

请参阅堆栈溢出问题如何为多行命令添加行注释。


尾部反斜杠必须是该行的最后一个字符,以便将其解释为延续命令。之后不允许任何评论甚至空格。

您应该能够在命令之间添加注释行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# output MYSQLDUMP file
cat ${MYSQLDUMP} | \
# simplify the line
sed '/created_at/d' | \
# create some newlines
tr",;""
"
| \
# use some sed magic
sed -e 's/[asbi]:[0-9]*[:]*//g' -e '/^[{}]/d' -e 's/""//g' -e '/^"{/d' | \
# more magic
sed -n -e '/^"/p' -e '/^print_value$/,/^option_id$/p' | \
# even more magic
sed -e '/^option_id/d' -e '/^print_value/d' -e 's/^"\(.*\)"$/\1/' | \
tr"
"
"," | \
# I hate phone numbers in my output
sed -e 's/,\([0-9]*-[0-9]*-[0-9]*\)/
\1/g'
-e 's/,$//' | \
# one more sed call and then send it to the CSV file
sed -e 's/^/"/g' -e 's/$/"/g' -e 's/,/","/g' >> ${CSV}


正如DigitalRoss所指出的那样,当线路以|结束时,不需要尾随反斜杠。你可以在|之后的一行上添加注释:

1
2
3
4
5
6
7
8
9
10
11
12
 cat ${MYSQLDUMP} |         # Output MYSQLDUMP file
 sed '1d' |                 # skip the top line
 tr",;""
"
|
 sed -e 's/[asbi]:[0-9]*[:]*//g' -e '/^[{}]/d' -e 's/""//g' -e '/^"{/d' |
 sed -n -e '/^"/p' -e '/^print_value$/,/^option_id$/p' |
 sed -e '/^option_id/d' -e '/^print_value/d' -e 's/^"\(.*\)"$/\1/' |
 tr"
"
"," |
 sed -e 's/,\([0-9]*-[0-9]*-[0-9]*\)/
\1/g'
-e 's/,$//' |   # hate phone numbers
 sed -e 's/^/"/g' -e 's/$/"/g' -e 's/,/","/g' >> ${CSV}

反斜杠转义#,将其解释为文字字符而不是注释字符。


$IFS评论黑客

这个hack使用$IFS上的参数扩展,用于分隔命令中的单词:

1
2
$ echo foo${IFS}bar
foo bar

同理:

1
2
$ echo foo${IFS#comment}bar
foo bar

使用它,您可以在带有contination的命令行上发表评论:

1
2
3
$ echo foo${IFS# Comment here} \
> bar
foo bar

但评论需要在\继续之前。

请注意,参数扩展在注释中执行:

1
2
3
4
5
6
$ ls file
ls: cannot access 'file': No such file or directory
$ echo foo${IFS# This command will create file: $(touch file)}bar
foo bar
$ ls file
file

罕见的例外

唯一罕见的情况是,如果$IFS以前以通过扩展删除的确切文本开始(即,在#字符之后):

1
2
3
4
5
$ IFS=x
$ echo foo${IFS#y}bar
foo bar
$ echo foo${IFS#x}bar
foobar

请注意,最终foobar没有空格,说明了问题。

由于$IFS默认只包含空格,因此您不太可能遇到此问题。

感谢@ pjh的评论引发了这个答案。


除了DigitalRoss的示例之外,如果您更喜欢$()而不是反引号`,这里可以使用另一种形式

1
2
3
echo abc $(: comment) \
     def $(: comment) \
     xyz

当然,您也可以使用带反引号的冒号语法:

1
2
3
echo abc `: comment` \
     def `: comment` \
     xyz

补充说明

$(#comment)不起作用的原因是因为一旦它看到#,它就会将该行的其余部分视为注释,包括右括号:comment)。所以括号永远不会关闭。

反引号解析不同,即使在#之后也会检测到关闭反引号。


这是一个bash脚本,它结合了以前几条注释的思想和习惯用语,通过示例提供了具有一般形式${__+ }的内联注释。

特别是

  • 可以是多行的
  • 未参数展开
  • 没有产生子进程(因此注释有效)

有一个限制,即不平衡支撑'}',括号')'必须受到保护(即'\}''\)')。

本地bash环境有一个要求:

  • 必须取消设置参数名称__

任何其他语法上有效的bash参数名称将代替__,前提是该名称没有设置值。

下面是一个示例脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# provide bash inline comments having the form
#     <wyn> ${__+ <comment>} <wyn>
#     <wyn> ${__+ <multiline
#                   comment>} <wyn>

# utility routines that obviate"useless use of cat"
function bashcat { printf '%s
'
"$(</dev/stdin)"; }
function scat { 1>&2 bashcat; exit 1; }

# ensure that '__' is unset && remains unset
[[ -z ${__+x} ]] &&  # if '__' is unset
  declare -r __ ||   # then ensure that '__' remains unset
  scat <<EOF         # else exit with an error
Error: the parameter __='${__}' is set, hence the
  comment-idiom '\${__+ <comment text>}' will fail
EOF

${__+ (example of inline comments)
------------------------------------------------
the following inline comment-idiom is supported
    <wyn> ${__+ <comment>} <wyn>
    <wyn> ${__+ <multiline
                  comment>} <wyn>
(advisory) the parameter '__' must NOT be set;
  even the null declaration __='' will fail
(advisory) protect unbalanced delimiters \} and \)
(advisory) NO parameter-expansion of <comment>
(advisory) NO subprocesses are spawned
(advisory) a functionally equivalent idiom is
    <wyn> `# <comment>` <wyn>
    <wyn> `# <multiline
               comment>` <wyn>
however each comment spawns a bash subprocess
that inelegantly requires ~1ms of computation
------------------------------------------------}