Комментирование в скрипте Bash внутри многострочной команды

165

Как я могу прокомментировать каждую строку следующих строк из скрипта?

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

Можно ли здесь комментировать?

BassKozz
источник
1
Ну, как вы заметили, если вы делаете # first, то \ становится просто частью комментария, но если вы делаете \ first, тогда более поздние символы в строке изменяют свое значение с «продолжения строки» на «quote». Я подумал об одном решении, приведенном ниже.
DigitalRoss

Ответы:

204

Это будет иметь некоторые накладные расходы, но технически это действительно ответ на ваш вопрос:

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

См. Вопрос переполнения стека. Как разместить комментарий к строке для многострочной команды .

DigitalRoss
источник
1
Кажется довольно сложным, если нет более простого метода?
BassKozz
1
Хорошо, я добавил немного более простой вариант.
DigitalRoss
1
Можете ли вы изменить свой ответ, просто чтобы показать, что обратная косая черта не нужна, чтобы я мог поместить комментарии рядом с каждой строкой и просто использовать конвейер?
BassKozz
Я проверил, что версии один и два работают. Тем не менее, вы можете объяснить, почему они это делают и что здесь происходит? Спасибо.
Фахим Митха
1
Спасибо за объяснение. Я открыл вопрос по unix.sx, требуя более подробной информации, многострочной команды bash с комментариями после символа продолжения .
Фахим Митха
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
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}
чернь
источник
5

Обратная косая черта экранирует знак #, интерпретируя его как его буквальный символ вместо символа комментария.

tobiasvl
источник
3

$IFS комментарий взломать

Этот хак использует расширение параметра on $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) . Так что скобки никогда не закрываются.

Обратные разборы обрабатываются по-разному и обнаруживают закрывающий обратный удар даже после a #.

wisbucky
источник
1
Будет ли это создавать новую оболочку для каждого комментария?
Ионикс
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 
------------------------------------------------}
Джон Сидлес
источник