在多行命令中的Bash脚本中进行注释


164

如何在脚本中对以下各行的每一行进行注释?

cat ${MYSQLDUMP} | \
sed '1d' | \
tr ",;" "\n" | \
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 "\n" "," | \
sed -e 's/,\([0-9]*-[0-9]*-[0-9]*\)/\n\1/g' -e 's/,$//' | \
sed -e 's/^/"/g' -e 's/$/"/g' -e 's/,/","/g' >> ${CSV}

如果我尝试添加以下评论:

cat ${MYSQLDUMP} | \ # Output MYSQLDUMP File

我得到:

#: not found

在这里可以发表评论吗?


1
好了,正如您所注意到的,如果先执行#,则\只是注释的一部分,但是如果先执行\,则该行上的后面的字符会将其含义从“行继续”更改为“引号”。我想到了一种解决方案,如下所示。
DigitalRoss

Answers:


203

这会有一些开销,但是从技术上讲,它确实可以回答您的问题:

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

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

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
似乎比较复杂,如果没有更简单的方法?
BassKozz

1
好的,我添加了一个稍微简单的变体。
DigitalRoss

1
您可以修改答案只是为了表明不需要反斜杠这一事实,因此我可以将注释放在每行旁边,而只需使用管道即可?
BassKozz

我验证了版本1和版本2可以正常工作。但是,您能解释一下他们为什么这样做以及这里发生了什么吗?谢谢。
Faheem Mitha

1
感谢您的解释。我在unix.sx上打开了一个问题,询问更多详细信息,bash多行命令,在连续字符后加注释
Faheem Mitha

39

尾部反斜杠必须是该行上的最后一个字符,才能将其解释为连续命令。后面不能添加任何注释,甚至不允许使用空格。

您应该能够在命令之间插入注释行

# output MYSQLDUMP file
cat ${MYSQLDUMP} | \
# simplify the line
sed '/created_at/d' | \
# create some newlines
tr ",;" "\n" | \
# 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 "\n" "," | \
# I hate phone numbers in my output
sed -e 's/,\([0-9]*-[0-9]*-[0-9]*\)/\n\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}

12
当管道命令组件以|结尾时,\不必要。
DigitalRoss

2
DigitalRoss,您是正确的,我可以只使用管道而不使用反斜杠,然后我的#comments可以正常工作...您可以将其发布为答案,以便我接受。
BassKozz

8
“您应该能够在命令之间插入注释行”:不,这仅是有效的,因为前几行的最后一个解释字符是|。如果你尝试的话cat file1\<newline>#comment<newline>file2,你会发现你不会得到cat file1 file2,而是cat file1; file2
dubiousjim 2012年

5
但是,正如其他人所提到的,cat file1 | # comment<newline>sort效果很好。也是如此cat file1 && # comment<newline>echo foo。因此,注释可以包含在|&&或之后||,但不能包含在\或命令中间。
dubiousjim

7

正如DigitalRoss指出的那样,当行末尾为时,不需要尾随反斜杠|。您可以在后面的一行上添加注释|

 cat ${MYSQLDUMP} |         # Output MYSQLDUMP file
 sed '1d' |                 # skip the top line
 tr ",;" "\n" | 
 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 "\n" "," |
 sed -e 's/,\([0-9]*-[0-9]*-[0-9]*\)/\n\1/g' -e 's/,$//' |   # hate phone numbers
 sed -e 's/^/"/g' -e 's/$/"/g' -e 's/,/","/g' >> ${CSV}


3

$IFS 评论骇客

本hack用途参数扩展$IFS,其被用于分离词语的命令:

$ echo foo${IFS}bar
foo bar

类似地:

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

使用此功能,您可以在命令行中以连续形式添加注释:

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

但评论必须在\继续之前进行。

请注意,参数扩展是在注释内部执行的:

$ 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以前以通过扩展名删除的确切文本开头(即,#字符之后):

$ IFS=x
$ echo foo${IFS#y}bar
foo bar
$ echo foo${IFS#x}bar
foobar

注意决赛foobar没有空格,说明了这个问题。

由于$IFS默认情况下仅包含空格,因此不可能会遇到此问题。


感谢@ PJH的评论这引发了这样的回答。


1

除了DigitalRoss的示例外,如果您愿意使用$()反引号,还可以使用另一种形式`

echo abc $(: comment) \
     def $(: comment) \
     xyz

当然,您也可以将冒号语法与反引号一起使用:

echo abc `: comment` \
     def `: comment` \
     xyz

补充笔记

之所以$(#comment)无效,是因为一旦看到#,便会将行的其余部分视为注释,包括右括号:comment)。因此,括号永远不会关闭。

反引号的解析方式有所不同,即使在结束后也会检测到结束的反勾号#


1
这会为每个评论创建一个新的shell吗?
lonix

0

这是一个bash脚本,结合了一些先前注释的思想和惯用语,并提供了带有常规形式的内嵌注释的示例,并带有示例${__+ <comment text>}

特别是

  • <comment text> 可以多行
  • <comment text> 没有参数扩展
  • 没有产生任何子流程(因此注释是有效的)

对有一个限制<comment text>,即不平衡的花括号'}'和括号')'必须得到保护(即'\}''\)')。

对本地bash环境有一个要求:

  • 参数名称__必须未设置

语法上有效的bash参数名称都可以代替__,只要该名称没有设置值即可。

以下是示例脚本

# provide bash inline comments having the form
#     <code> ${__+ <comment>} <code> 
#     <code> ${__+ <multiline
#                   comment>} <code>

# utility routines that obviate "useless use of cat"
function bashcat { printf '%s\n' "$(</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
    <code> ${__+ <comment>} <code> 
    <code> ${__+ <multiline
                  comment>} <code> 
(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 
    <code> `# <comment>` <code> 
    <code> `# <multiline
               comment>` <code>
however each comment spawns a bash subprocess
that inelegantly requires ~1ms of computation 
------------------------------------------------}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.