การแสดงความคิดเห็นในสคริปต์ 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

เป็นไปได้ไหมที่จะแสดงความคิดเห็นที่นี่?


1
อย่างที่คุณสังเกตถ้าคุณทำ # อันดับแรกแล้ว \ กลายเป็นเพียงส่วนหนึ่งของความคิดเห็น แต่ถ้าคุณทำ \ ก่อนแล้วตัวละครในบรรทัดหลังจากนั้นเปลี่ยนความหมายของมันออกไปจาก ฉันคิดถึงวิธีแก้ปัญหาหนึ่งข้อตามด้านล่าง
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

คำถามดูกองมากเกินวิธีการใส่สายแสดงความคิดเห็นสำหรับหลายบรรทัดคำสั่ง


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 คุณถูกต้องฉันสามารถใช้ไพพ์และไม่ใช่แบ็กสแลชแล้ว #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 ชี้ให้เห็นเครื่องหมายทับขวาต่อท้ายไม่จำเป็นเมื่อสาย woud |สิ้นสุดใน และคุณสามารถใส่ความคิดเห็นในบรรทัดต่อไปนี้|:

 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 แล้วนี่เป็นอีกรูปแบบหนึ่งที่คุณสามารถใช้หากคุณต้องการ$()แทน backticks`

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

แน่นอนคุณสามารถใช้ซินแท็กซ์ของลำไส้ใหญ่กับ backticks ได้เช่นกัน:

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

หมายเหตุเพิ่มเติม

เหตุผลที่$(#comment)ไม่ทำงานเป็นเพราะเมื่อมันเห็นก็ถือว่าส่วนที่เหลือของสายเป็นความคิดเห็นรวมทั้งวงเล็บปิดไปนี้:# comment)ดังนั้นจึงไม่ปิดวงเล็บ

backticks แยกแตกต่างกันและจะตรวจสอบ backtick #ปิดแม้หลังจากที่


1
มันจะสร้างเชลล์ใหม่สำหรับทุกความคิดเห็นหรือไม่?
lonix

0

${__+ <comment text>}นี่เป็นสคริปต์ทุบตีที่ผสมผสานความคิดและสำนวนความเห็นหลายครั้งก่อนหน้าเพื่อให้มีตัวอย่างความคิดเห็นแบบอินไลน์ที่มีรูปแบบทั่วไป

โดยเฉพาะอย่างยิ่ง

  • <comment text> สามารถหลายบรรทัด
  • <comment text> ไม่ได้ขยายพารามิเตอร์
  • ไม่มีโพรเซสวางไข่ (ดังนั้นความเห็นจึงมีประสิทธิภาพ)

มีข้อ จำกัด เพียงประการเดียว<comment text>คือต้องมีการป้องกันวงเล็บปีกกา'}'และวงเล็บที่ไม่สมดุล')'(เช่น'\}'และ'\)' )

มีข้อกำหนดหนึ่งประการเกี่ยวกับสภาพแวดล้อมการทุบตีท้องถิ่น:

  • ชื่อพารามิเตอร์__จะต้องไม่มีการตั้งค่า

พารามิเตอร์ bash-name ที่ถูกต้องอื่น ๆ จะแสดงแทน __โดยที่ชื่อนั้นไม่มีค่าที่ตั้งไว้

สคริปต์ตัวอย่างต่อไปนี้

# 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 
------------------------------------------------}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.