ฉันจะลบความคิดเห็นทั้งหมดจากไฟล์ได้อย่างไร


21

ฉันมีไฟล์ที่มีความคิดเห็น:

foo
bar
stuff
#Do not show this...
morestuff
evenmorestuff#Or this

ฉันแค่ต้องการพิมพ์รหัสที่ไม่ใส่เครื่องหมายทั้งหมด:

foo
bar
stuff
morestuff
evenmorestuff

ความสามารถในการตัดความคิดเห็นออกจากไฟล์เป็นสิ่งสำคัญ ... วิธีการที่ดีคืออะไร


1
คุณไม่สามารถลบส่วนของบรรทัดด้วย grep ได้ คุณสามารถใช้ sed สำหรับสิ่งนี้ได้
miracle173

2
ข้อความและตัวอย่างของคุณขัดแย้ง คุณเขียนเกี่ยวกับบรรทัดที่ถูกคอมเม้นต์ แต่ชัดเจนจากบรรทัดสุดท้ายที่คุณหมายถึงส่วนของเส้น จากนั้นบรรทัดแรกที่มีความคิดเห็นจะถูกลบรวมถึง EOL และวินาทีที่สองอาจเป็น แต่ไม่ชัดเจนเนื่องจากเป็นบรรทัดสุดท้าย โปรดใช้ถ้อยคำใหม่ 'บรรทัดที่ใส่ความคิดเห็นไว้' เพื่อให้ถูกต้องและทำให้เข้าใจผิดตัวอย่างของคุณ
Anthon

5
awk -F\# '$1!="" { print $1 ;} 'ลองใช้
Archemar

2
เส้นแบบไหนที่echo '#' # output a #จะจัดการ?
Kusalananda

3
@Questionmark ฉันอาจจะฉลาด แต่ฉันไม่ได้เขียน -a-shell-grammar-parser
Kusalananda

คำตอบ:


40

วิธีหนึ่งในการลบความคิดเห็นทั้งหมดคือใช้grepกับ-oตัวเลือก:

grep -o '^[^#]*' file

ที่ไหน

  • -o: พิมพ์เฉพาะส่วนที่ตรงกันของบรรทัด
  • แรก^: จุดเริ่มต้นของบรรทัด
  • [^#]*: ตัวละครใด ๆ ยกเว้น#ซ้ำศูนย์หรือมากกว่าครั้ง

โปรดทราบว่าบรรทัดว่างจะถูกลบเช่นกัน แต่บรรทัดที่มีช่องว่างเท่านั้นจะยังคงอยู่


2
ฉันจะใช้grep -v '^#' file > newfilewithoutcomments
Basile Starynkevitch

1
ควรสังเกตว่านี่ไม่ใช่วิธีทั่วไปสำหรับเชลล์สคริปต์เช่นบรรทัดsomvar='I am a long complicated string ## with special characters' # and I am a commentจะไม่ได้รับการจัดการอย่างถูกต้อง
Wildcard

ตัวแปรนี้ทำงานได้ดีขึ้นสำหรับผม (บน Mac):grep -o '^[^#].*' file
Pierz

ความคิดเห็นหายไป แต่ฉันเห็นพื้นที่สีขาวจำนวนหนึ่งอยู่ในที่ของพวกมัน sedวิธีแก้ปัญหามีเพียงหนึ่งบรรทัดว่างดูเหมือนว่าอาร์กิวเมนต์ที่มั่นคงที่จะใช้คำตอบอื่น ๆ เว้นแต่ฉันจะหายไปบางสิ่งบางอย่าง?
JBallin

@JBallin คุณได้กำหนดนามแฝงบางอย่างแล้วgrepหรืออาจ? ลองเปลี่ยนgrepเป็นcommand grepถ้าคุณยังเห็นช่องว่างโพสต์ตัวอย่างอินพุต
jimmij

31

ฉันเชื่อว่าsedสามารถทำงานได้ดีกว่านี้grepมาก บางสิ่งเช่นนี้

sed '/^[[:blank:]]*#/d;s/#.*//' your_file

คำอธิบาย

  • sedโดยค่าเริ่มต้นดูที่ไฟล์ของคุณทีละบรรทัดแล้วพิมพ์แต่ละบรรทัดหลังจากอาจใช้การแปลงในเครื่องหมายคำพูด ( sed '' your_fileจะพิมพ์บรรทัดทั้งหมดไม่เปลี่ยนแปลง)
  • ที่นี่เราให้sedคำสั่งสองคำสั่งเพื่อดำเนินการในแต่ละบรรทัด (โดยคั่นด้วยเครื่องหมายอัฒภาค)
  • คำสั่งแรกบอกว่า: /^[[:blank:]]*#/d. ในภาษาอังกฤษหมายความว่าหากบรรทัดตรงกับแฮชที่จุดเริ่มต้น (นำหน้าด้วยจำนวนช่องว่างนำหน้า) ให้ลบบรรทัดนั้น (บรรทัดนั้นจะไม่ถูกพิมพ์)
  • คำสั่งที่สองคือ: s/#.*//. ในภาษาอังกฤษนั่นคือแทนที่เครื่องหมายแฮชแล้วตามด้วยสิ่งต่าง ๆ มากมายเท่าที่คุณจะหาได้ (จนถึงจุดสิ้นสุดของบรรทัดนั่นคือ) โดยไม่มีสิ่งใด (ไม่มีสิ่งใดเป็นพื้นที่ว่างระหว่างสองครั้งสุดท้าย//)
  • โดยสรุปการดำเนินการนี้จะดำเนินการผ่านบรรทัดการลบไฟล์ของคุณซึ่งประกอบด้วยความคิดเห็นทั้งหมดและบรรทัดใด ๆ ที่เหลืออยู่หลังจากนั้นจะมีความคิดเห็นที่เต็มไปด้วยความคิดเห็นเหล่านั้น

1
มันจะลบสิ่งที่พบหลังจากแฮชภายในสตริงด้วยไม่ใช่หรือ? เช่นmystring="Hello I am a #hash" จะกลายเป็น mystring="Hello I am a"
javadba

@javadba ใช่ แต่ ณ จุดนี้คุณอาจใช้โปรแกรมแยกวิเคราะห์เต็มรูปแบบได้เช่นกัน อะไรจะใช้ข้อมูลนี้ที่สามารถเข้าใจคำพูดและการกำหนดตัวแปร แต่ไม่สามารถจัดการความคิดเห็นได้ (นี่คือสาเหตุที่ไฟล์ปรับแต่งจำนวนมากเช่นcrontabอนุญาตเฉพาะความคิดเห็นแบบเต็มบรรทัดโดยมีหรือไม่มีช่องว่างนำหน้า แต่ไม่อนุญาตให้แสดงความคิดเห็นต่อท้ายบนบรรทัดตรรกะคือง่ายกว่ามากใช้คำสั่ง Sed แรกในคำตอบนี้สองคำเท่านั้น สำหรับผู้แสดงความคิดเห็น crontab)
Wildcard

คำตอบที่ดีดูเหมือนว่าจะมีความสมดุลระหว่างยูทิลิตี้และความซับซ้อนสำหรับกรณีการใช้งานทั่วไป แต่ในกรณีที่คุณรู้ล่วงหน้าว่าคุณจะต้องลบบรรทัดที่ขึ้นต้นด้วย#(ในคอลัมน์ 1) เท่านั้น มีประโยชน์sedมากกว่าgrep -v "^#"หรือไม่
RBF06

4

คุณสามารถบรรลุผลลัพธ์ที่ต้องการโดยใช้คำสั่ง sed คำสั่งด้านล่างได้ทำเคล็ดลับสำหรับฉัน

sed 's/#.*$//g' FileName

ที่ไหน

  • #.*$- Regexp จะกรองสตริงทั้งหมดที่ขึ้นต้นด้วย#จนถึงจุดสิ้นสุดของบรรทัด

ที่นี่เราจำเป็นต้องลบบรรทัดเหล่านั้นดังนั้นเราจึงแทนที่ด้วยว่างเพื่อข้ามส่วน 'แทนที่'

  • g - กล่าวถึงการค้นหาซ้ำของรูปแบบจนกว่าจะถึงจุดสิ้นสุดไฟล์

ไวยากรณ์ทั่วไปของ sed: s/regexp/replacement/flags FileName


2
หมายเหตุ: บรรทัดที่ 4 ถูกแทนที่ด้วยบรรทัดใหม่ในกรณีนี้
αғsнιη

1
ลองใช้สคริปต์ที่มีsedคำสั่งนั้น...
Kusalananda

มันจะไม่จัดการprint "#tag" # Print a hashtag.
Ray Butterworth

3

ดังที่คนอื่น ๆ ได้ชี้ให้เห็นเครื่องมือที่ใช้ข้อความและอื่น ๆ ทำงานได้ไม่ดีนักหากส่วนใดส่วนหนึ่งของสคริปต์ดูเหมือนความคิดเห็น แต่จริงๆแล้วไม่ใช่ ตัวอย่างเช่นคุณสามารถหา # ภายในสตริงหรือร่วมกันมากกว่าและ$#${#param}

ฉันเขียนฟอร์แมตเชลล์ชื่อshfmtซึ่งมีคุณสมบัติในการย่อขนาดโค้ด ซึ่งรวมถึงการลบความคิดเห็นเหนือสิ่งอื่นใด:

$ cat foo.sh
echo $# # inline comment
# lone comment
echo '# this is not a comment'
[mvdan@carbon:12] [0] [/home/mvdan]
$ shfmt -mn foo.sh
echo $#
echo '# this is not a comment'

parser และเครื่องพิมพ์คือแพ็คเกจ Go ดังนั้นหากคุณต้องการโซลูชันที่กำหนดเองคุณควรเขียนโปรแกรม Go-line 20 บรรทัดเพื่อลบความคิดเห็นในแบบที่คุณต้องการ


2

คุณสามารถใช้การจับคู่แบบกลับด้านได้:

    #grep -v "#" filename

-v, - invert-match กลับด้านความรู้สึกของการจับคู่เพื่อเลือกบรรทัดที่ไม่ตรง (-v ถูกระบุโดย POSIX)


2
@alinh ขอบคุณสำหรับการตรวจสอบคำตอบ โปรดทราบว่าคำถามที่ต้องการไม่เพียง แต่จุดเริ่มต้นของบรรทัด แต่ที่ใดก็ได้ในไฟล์ สิ่งนี้ยังแสดงในผลลัพธ์ที่คาดหวังของเขา / เธอในคำถามข้างต้น คำตอบของฉันจะไม่ถูกต้องหากฉันมองหาจุดเริ่มต้นของบรรทัดเท่านั้น
Raza

ZZZ เลวของฉันไม่เห็นบรรทัดสุดท้าย :(
alinh

1
นี่จะเป็นการลบบรรทัดที่เริ่มต้นด้วยevenmorestuffในตัวอย่างของ OP อย่างสมบูรณ์
โจเซฟอาร์

@JosephR จับดี. ฉันพลาดไปก่อนหน้านี้ ในกรณีนี้grep -o '^[^#]*' fileจะเป็นทางออกที่ดีที่สุด นี่คือคำอธิบายแล้วโดย jimmij ขอบคุณสำหรับความคิดเห็นของคุณ
Raza

มันจะไม่จัดการprint "#tag" # Print a hashtag.
Ray Butterworth

2

ฉันชอบคำตอบของ joseph แต่ต้องการให้ตัด // ความคิดเห็นด้วยดังนั้นฉันจึงแก้ไขเล็กน้อยและทดสอบบน redhat

# no comments alias
alias nocom="sed -E '/^[[:blank:]]*(\/\/|#)/d;s/#.*//' | strings"

# example
cat SomeFile | nocom | less

ฉันเดิมพันว่ามีวิธีที่ดีกว่าในการลบบรรทัดว่างเปล่ากว่าการใช้สตริง แต่มันเป็นทางออกที่รวดเร็วและสกปรกที่ฉันใช้

-cheers


มันจะไม่จัดการprint "#tag" # Print a hashtag.
Ray Butterworth


1
cat YOUR_FILE | cut -d'#' -f1

มันใช้#เป็นตัวแยกคอลัมน์และเก็บเพียงคอลัมน์แรก (นั่นคือทุกอย่างก่อน#)


1
หากYOUR_FILEเป็นสคริปต์ที่มีคำสั่งเหล่านั้นสคริปต์จะปล่อยไว้cat YOUR_FILE | cut -'ในไฟล์บนบรรทัดนั้น
Kusalananda

1

ใช้การแสดงออกเช่น

egrep -v "#|$^" <file-name> 

: -v: จะสลับการจับคู่

: #: จะจับคู่ทุกบรรทัดที่ขึ้นต้นด้วย #

: $ ^: จะจับคู่บรรทัดว่างทั้งหมด


1
ไม่ความ#ตรงจะตรงกับที่ใดก็ได้ในบรรทัดและลบทั้งบรรทัด
ilkkachu

1

ทางออกที่ดีที่สุดคือการใช้คำสั่ง:

sed -i.$(date +%F) '/^#/d;/^$/d' ntp.conf

-i คือการแก้ไขในสถานที่ แต่คำนำหน้าโดยตรงต่อไปบอก sed เพื่อสร้างการสำรองข้อมูล ในกรณีนี้ด้วยส่วนขยายวันที่ (ntp.conf.date) เราเรียกใช้สองคำสั่งแต่ละคำสั่งด้วยช่องว่างที่อยู่ก่อนอื่นจะลบบรรทัดที่ถูกคอมเม้นต์และอันที่สองแยกออกจากส่วนแรกด้วยเซมิโคลอนแล้วลบบรรทัดว่างออก

ฉันพบวิธีแก้ปัญหานี้เมื่อ: theurbanpenguin.com


0

ไม่มีคำตอบอื่นใดที่ดูเหมือนจะทำเพื่อความยุติธรรมพวกเขาอาจจะทิ้งบรรทัดว่างเปล่าหรือปล่อยให้เป็นบรรทัดที่ความคิดเห็นไม่ได้อยู่ที่ตัวอักษรตัวแรก ฉันลงเอยด้วยการใช้สิ่งนี้:

cat << EOF >> ~/.bashrc
alias nocom='sed -e "/^\s*#/d" -e "/^\s*$/d"'
EOF

วิธีนี้จะตั้งค่านามแฝงเพื่อที่คุณจะได้ไม่ต้องจดจำ (ซึ่งเป็นไปไม่ได้ที่จะเริ่มต้นด้วย) เปิดเซสชันใหม่และคุณจะมีnocomคำสั่งใหม่ จากนั้นคุณสามารถ

nocom /etc/foobar.conf

ไชโย


1
มีจุดไม่มากในการจับคู่.*$ใน regex แรก - สมอไม่เป็นประโยชน์และคุณไม่ได้จับข้อความที่ตรงกันเพื่อใช้ในการแทนที่ ใช้เพียง^\s*
Jeff Schaller

มันจะไม่จัดการprint "#tag" # Print a hashtag.
Ray Butterworth


-1

ฉันโพสต์สิ่งที่ได้ผลสำหรับฉันและดูเหมือนจะสมเหตุสมผลที่สุดหลังจากอ่านผ่าน ๆ พร้อมคำอธิบาย มีสองโพสต์เข้ามาใกล้ แต่ฉันยังไม่สามารถคอมเม้นได้ (เพราะฉันยังใหม่):

grep -E -v "(^#.*|^$)" filename
  • -E = ตีความรูปแบบต่อไปนี้เป็นนิพจน์ทั่วไปซึ่งคล้ายกับการใช้ egrep
  • -v = พิมพ์ผกผันของรูปแบบ (บรรทัดที่ไม่ตรงกับนิพจน์จะถูกพิมพ์)
  • "(^#.*|^$)"= มีท่อที่กำหนดคำสั่ง OR นิพจน์นี้บอกว่าจะพิมพ์บรรทัดใด ๆ ที่ขึ้นต้นด้วย#(และอะไรก็ได้หลังจากนั้น) หรือบรรทัดใด ๆ ที่มีอักขระเป็นศูนย์ระหว่างจุดเริ่มต้นและจุดสิ้นสุดของบรรทัด

-vจะพิมพ์บนหน้าจอผกผันของที่ซึ่งจะเป็นสายใด ๆ #กับตัวละครที่ไม่ได้เริ่มต้นด้วย


มันจะไม่จัดการ print "#tag" # Print a hashtag.
Ray Butterworth

ใช่แล้ว ... แน่นอน ขอบคุณสำหรับการชี้ให้เห็นว่า ฉันกำลังมองหาคำตอบเกี่ยวกับไฟล์การกำหนดค่าลินุกซ์ทั่วไปเช่น pam.d configs ดังนั้นฉันจึงไม่คิดอย่างนั้น ฉันเดาว่ามันจะต้องถูกดัดแปลงเพื่อค้นหาและลบความคิดเห็นใด ๆ ที่อยู่ในบรรทัดเดียวกันกับรหัส ฉันเพิ่งเห็นว่าอาจเป็นทางออกที่ดีกว่าสำหรับปัญหาเฉพาะของฉันด้านบน: egrep -v "# | $ ^"
jackbmg
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.