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

在多行命令内的Bash脚本中进行注释,bash,syntax,comments,Bash,Syntax,Comments,如何对脚本中的以下每一行进行注释 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

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

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

可以在这里发表评论吗?

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

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

请参阅堆栈溢出问题。

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

尾部反斜杠必须是行上的最后一个字符,才能解释为连续命令。之后不允许有任何注释,甚至不允许有空格


您应该能够在命令之间放置注释行

# 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}

正如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}
$IFS
评论黑客 此黑客在
$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
之前以通过扩展删除的确切文本开头(即,在
字符之后):

注意最后的
foobar
没有空格,说明了问题

由于默认情况下,
$IFS
只包含空格,因此您极不可能遇到此问题



引发这个答案的功劳

下面是一个bash脚本,它结合了前面几个注释的思想和习惯用法,以示例的形式提供具有一般形式的内联注释
${{uu+}

特别是

  • 可以是多行的
  • 未展开参数
  • 没有生成子流程(因此注释是有效的)
有一个限制,即必须保护不平衡的大括号
'}'
和括号
'
(即
'\}'
'\')

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

  • 必须取消设置参数名
    \uuu
如果名称没有设置值,则任何其他语法上有效的bash参数名称将代替
\uuu

下面是一个示例脚本

# 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 
------------------------------------------------}

除了DigitalRoss的示例之外,如果您更喜欢
$()
而不是backticks
`

echo abc$(:注释)\
def$(:注释)\
xyz
当然,您也可以将冒号语法与反勾号一起使用:

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

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


Backticks的解析方式不同,即使在执行
#

后,也会检测到关闭的backtick。对于管道连接的命令,我首选的编码样式是

command1\
|命令2\
| ...
正如和其他人所建议的,注释行的一种方法是

command1\
|#内联评论
命令2\
| ...
另一种不调用子shell的方法是使用Bash的
{list;}
构造,它总是有效的。因此,这里:

command1\
| {
#内联注释
命令2
} \
| ...

而不是您尝试的:

cat ${MYSQLDUMP} | \ # Output MYSQLDUMP File
其他人提到,这应该是可行的:

cat ${MYSQLDUMP} |   # Output MYSQLDUMP File

由于分割线并不总是以管道(|)结尾,因此,您可以将注释放在它们自己的行上,如下所示:

date && \
  # List current directory
  ls -l | awk '{ \
  # Filename is in the ninth column
      # This is just making "ls -l" work mostly like "ls -1"
  print $9 }'

只是在字符串的中间不要这样做:

echo " Hello \
 # Localized name for your planet:
world."
在您的情况下,您可以使用以下方法:

cat ${MYSQLDUMP} | \
# Output MYSQLDUMP File
扩展示例:

# Create .csv file from MySQL dump file
cat ${MYSQLDUMP} |   
# Output MYSQLDUMP File
# and pipe to first sed command
sed '1d' | \
# Pipe output to tr
tr ",;" "\n" | \
# Apply sed expression
sed -e 's/[asbi]:[0-9]*[:]*//g' -e '/^[{}]/d' -e 's/""//g' -e '/^"{/d' | \
    # Apply another two sed expressions
    # (and since whitespace is ignored, you can intent for clarity)
    sed -n -e '/^"/p' -e '/^print_value$/,/^option_id$/p' | \
    # Apply three more sed expressions
    sed -e '/^option_id/d' -e '/^print_value/d' -e 's/^"\(.*\)"$/\1/' | \
    # Use tr to ...
    tr "\n" "," | \
    # Apply yet another two sed expressions
    sed -e 's/,\([0-9]*-[0-9]*-[0-9]*\)/\n\1/g' -e 's/,$//' | \
    # Apply the final three sed expressions
    sed -e 's/^/"/g' -e 's/$/"/g' -e 's/,/","/g' >> ${CSV}
。。。或者将两种方法混合使用:

# Create .csv file from MySQL dump file
cat ${MYSQLDUMP} |   # Output MYSQLDUMP File
# and pipe to first sed command
sed '1d' | \
# Pipe output to tr
...

(我相信这两种方法都可以工作,因为shell脚本文件是逐行解析的,就像CLI输入一样。)

最后说明:

  • 重要的是要记住,当使用行继续符(\)时,应该是该行的最后一个字符(即使是一个被遗忘的尾随空格也会毁掉你的夜晚)

  • 如果从命令行手动键入,如果要使用“命令历史记录”功能,请仅使用第二种方法(每条注释位于其自己的行上)

  • 如果使用历史记录并希望保留注释,请不要使用这两种方法中的任何一种-使用此问题不同答案中的一种


如果没有更简单的方法,似乎相当复杂?好的,我添加了一个稍微简单的变体。您是否可以修改您的答案,以表明不需要反斜杠,这样我就可以将注释放在每行旁边,只需使用管道?我验证了版本1和版本2可以工作。然而,你能解释一下他们为什么这么做,以及这里发生了什么吗?谢谢,谢谢你的解释。我在unix.sx上打开了一个问题,询问更多的细节。正如您所注意到的,如果您首先这样做,那么\将成为注释的一部分,但是如果您首先这样做,那么行中后面的字符将其含义从“行继续”改为“引用”。我想到了一个解决方案,如下所示。当管道命令组件以| DigitalRoss结尾时,不需要\的可能副本,你是对的,我可以只使用管道而不是反斜杠,然后我的#注释将完美地工作。。。你能不能把它作为一个答案贴出来,这样我就可以接受它。“你应该能够在你的命令之间放上注释行”:不,这只起作用,因为最后解释的字符是o
# Create .csv file from MySQL dump file
cat ${MYSQLDUMP} |   # Output MYSQLDUMP File
# and pipe to first sed command
sed '1d' | \
# Pipe output to tr
...