Коментування в сценарії 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

Відповіді:


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

Я перевірив, що одна і дві версії працюють. Однак ви можете пояснити, чому вони роблять і що тут відбувається? Дякую.
Faheem Mitha

1
Дякую за пояснення. Я відкрив питання на unix.sx з проханням отримати докладнішу інформацію, виконайте команду багаторядкової команди з коментарями після символу продовження .
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, Ви маєте рацію, я можу просто використовувати трубу, а не зворотну косу рису, і тоді мої # коментарі працюватимуть ідеально ... чи можете ви розмістити це як відповідь, щоб я міг прийняти це.
BassKozz

8
"Ви повинні мати можливість розміщувати рядки коментарів між своїми командами": ні, це працює лише тому, що останній інтерпретований символ попередніх рядків є |. Якщо ви спробуєте cat file1\<newline>#comment<newline>file2, ви побачите, що не отримаєте cat file1 file2, а скоріше cat file1; file2.
сумнівним

5
Однак, як згадували інші, cat file1 | # comment<newline>sortпрацює чудово. Так само і робить cat file1 && # comment<newline>echo foo. Тому коментарі можуть бути включені після |або &&або ||, але не після того, як `\` або в середині команди.
сумнівним

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

Зворотна косої риски уникає #, трактуючи його як буквальний символ замість символу коментаря.


3

$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попередньо почати з точного тексту, який видаляється за допомогою розширення (тобто після #символу):

$ 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
Чи це створить нову оболонку для кожного коментаря?
lonix

0

Ось базовий сценарій, який поєднує ідеї та ідіоми кількох попередніх коментарів, щоб надати приклади вбудованих коментарів загальної форми ${__+ <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 
------------------------------------------------}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.