Bình luận trong một tập lệnh Bash bên trong một lệnh đa dòng


164

Làm cách nào tôi có thể nhận xét về từng dòng của các dòng sau từ một tập lệnh?

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}

Nếu tôi cố gắng và thêm một nhận xét như:

cat ${MYSQLDUMP} | \ # Output MYSQLDUMP File

Tôi có:

#: not found

Có thể bình luận ở đây?


1
Chà, như bạn nhận thấy, nếu bạn làm # trước, thì \ sẽ chỉ là một phần của nhận xét, nhưng nếu bạn làm \ trước, thì các ký tự sau trên dòng sẽ thay đổi nghĩa của nó từ "tiếp tục dòng" thành "trích dẫn". Tôi đã nghĩ về một giải pháp, được đưa ra dưới đây.
DigitalRoss

Câu trả lời:


203

Điều này sẽ có một số chi phí, nhưng về mặt kỹ thuật nó trả lời câu hỏi của bạn:

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

Và đối với đường ống cụ thể, có một giải pháp sạch không có phí:

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

Xem câu hỏi về Stack Overflow Làm thế nào để đặt bình luận dòng cho một lệnh nhiều dòng .


1
Có vẻ khá phức tạp, nếu không có phương pháp đơn giản hơn?
BassKozz

1
Ok, tôi đã thêm một biến thể đơn giản hơn một chút.
DigitalRoss

1
Bạn có thể sửa đổi câu trả lời của mình chỉ để cho thấy thực tế là dấu gạch chéo ngược là không cần thiết để tôi có thể đặt các bình luận bên cạnh mỗi dòng và chỉ cần sử dụng một đường ống?
BassKozz

Tôi đã xác minh rằng phiên bản một và hai hoạt động. Tuy nhiên, bạn có thể giải thích tại sao họ làm và những gì đang xảy ra ở đây? Cảm ơn.
Faheem Mitha

1
Cảm ơn đã giải thích. Tôi đã mở một câu hỏi trên unix.sx để biết thêm chi tiết, bash lệnh đa dòng với các bình luận sau ký tự tiếp tục .
Faheem Mitha

39

Dấu gạch chéo ngược phải là ký tự cuối cùng trên dòng để nó được hiểu là lệnh tiếp tục. Không có bình luận hoặc thậm chí khoảng trắng được cho phép sau nó.

Bạn sẽ có thể đặt các dòng bình luận ở giữa các lệnh của bạn

# 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
\ Không cần thiết khi thành phần lệnh đường ống kết thúc bằng |
DigitalRoss

2
DigitalRoss, Bạn đã đúng, tôi chỉ có thể sử dụng đường ống chứ không phải dấu gạch chéo ngược và sau đó #comments của tôi sẽ hoạt động hoàn hảo ... bạn có thể đăng câu đó như một câu trả lời để tôi có thể chấp nhận nó không.
BassKozz

8
"Bạn sẽ có thể đặt các dòng bình luận ở giữa các lệnh của mình": không, điều này chỉ hoạt động vì ký tự được giải thích cuối cùng của các dòng trước đó là |. Nếu bạn thử cat file1\<newline>#comment<newline>file2, bạn sẽ thấy bạn không nhận được cat file1 file2, nhưng đúng hơn cat file1; file2.
dubiousjim

5
Tuy nhiên, như những người khác đã đề cập, cat file1 | # comment<newline>sorthoạt động tốt. Cũng vậy cat file1 && # comment<newline>echo foo. Vì vậy, các bình luận có thể được đưa vào sau |hoặc &&hoặc ||, nhưng không phải sau `\` hoặc ở giữa một lệnh.
dubiousjim

7

Như DigitalRoss đã chỉ ra, dấu gạch chéo ngược là không cần thiết khi dòng kết thúc |. Và bạn có thể đặt bình luận trên một dòng sau |:

 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

Dấu gạch chéo ngược thoát khỏi #, giải thích nó là ký tự theo nghĩa đen của nó thay vì ký tự nhận xét.


3

$IFS bình luận hack

Đây sử dụng Hack mở rộng thông số trên $IFS, được sử dụng các từ riêng biệt trong các lệnh:

$ echo foo${IFS}bar
foo bar

Tương tự:

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

Sử dụng điều này, bạn có thể đặt một nhận xét trên một dòng lệnh với sự tiếp tục:

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

nhưng bình luận sẽ cần phải được \tiếp tục.

Lưu ý rằng việc mở rộng tham số được thực hiện bên trong bình luận:

$ 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

Ngoại lệ hiếm

Trường hợp hiếm hoi duy nhất thất bại này là nếu $IFStrước đó đã bắt đầu với văn bản chính xác được xóa thông qua việc mở rộng (nghĩa là sau #ký tự):

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

Lưu ý cuối cùng foobar không có không gian, minh họa vấn đề.

Kể từ khi $IFSchỉ chứa khoảng trắng theo mặc định, nó là vô cùng khó bạn sẽ chạy vào vấn đề này.


Tín dụng cho bình luận của @ pjh đã châm ngòi cho câu trả lời này.


1

Ngoài các ví dụ của DigitalRoss, đây là một hình thức khác mà bạn có thể sử dụng nếu bạn thích $()thay vì backticks`

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

Tất nhiên, bạn cũng có thể sử dụng cú pháp dấu hai chấm với backticks:

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

Ghi chú bổ sung

Lý do $(#comment)không hoạt động là vì một khi nó nhìn thấy #, nó coi phần còn lại của dòng là nhận xét, bao gồm cả dấu ngoặc đơn đóng : comment). Vì vậy, dấu ngoặc đơn không bao giờ đóng.

Backticks phân tích cú pháp khác nhau và sẽ phát hiện backtick đóng ngay cả sau khi a #.


1
Điều đó sẽ tạo ra một vỏ mới cho mỗi bình luận?
lonix

0

Dưới đây là một tập lệnh bash kết hợp các ý tưởng và thành ngữ của một số bình luận trước đó để cung cấp, với các ví dụ, các bình luận nội tuyến có dạng chung ${__+ <comment text>}.

Đặc biệt

  • <comment text> có thể là nhiều dòng
  • <comment text> không được mở rộng tham số
  • không có quy trình con nào được sinh ra (vì vậy các bình luận có hiệu quả)

Có một hạn chế đối với <comment text>, cụ thể là, dấu ngoặc '}'và dấu ngoặc không cân bằng ')'phải được bảo vệ (nghĩa là '\}''\)').

Có một yêu cầu về môi trường bash cục bộ:

  • tên tham số __phải được đặt

Bất kỳ tên tham số bash hợp lệ nào khác sẽ phục vụ thay cho __ , với điều kiện tên đó không có giá trị được đặt.

Một kịch bản ví dụ sau

# 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 
------------------------------------------------}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.