sed แทนที่แท็บและช่องว่างทั้งหมดด้วยช่องว่างเดียว


23

ฉันได้รับสตริงเหมือนดังต่อไปนี้:

test.de.          1547    IN      SOA     ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600

ตอนนี้ฉันต้องการแทนที่แท็บ / ช่องว่างทั้งหมดในระหว่างระเบียนด้วยช่องว่างเดียวเพื่อให้ฉันสามารถใช้กับ cut -d " "

ฉันพยายามต่อไปนี้:

sed "s/[\t[:space:]]+/[:space:]/g"

และความหลากหลายต่าง ๆ แต่ไม่สามารถทำงานได้ ความคิดใด ๆ


ลอง: sed -r -e "s / [\ t \] + / / g"
RJS

ตัวเลือกการcutสนับสนุนของคุณ-wหรือไม่
Kondybas

คำตอบ:


40

ใช้ sed -e "s/[[:space:]]\+/ /g"

นี่คือคำอธิบาย:

[   # start of character class

  [:space:]  # The POSIX character class for whitespace characters. It's
             # functionally identical to [ \t\r\n\v\f] which matches a space,
             # tab, carriage return, newline, vertical tab, or form feed. See
             # https://en.wikipedia.org/wiki/Regular_expression#POSIX_character_classes

]   # end of character class

\+  # one or more of the previous item (anything matched in the brackets).

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

สิ่งที่+จะต้องหลบหนีใน regex เพราะด้วยเครื่องยนต์ regex ของ sed +เป็นตัวอักษรปกติในขณะที่\+metacharacter สำหรับ 'หนึ่งหรือมากกว่า' ในหน้า 86 ของMastering Regular Expressions , Jeffrey Friedl กล่าวไว้ในเชิงอรรถว่าเอ็ดและ grep ใช้วงเล็บหนีเพราะ "Ken Thompson รู้สึกว่านิพจน์ทั่วไปจะใช้ในการทำงานกับรหัส C เป็นหลักซึ่งจำเป็นต้องจับคู่วงเล็บดิบจะธรรมดากว่าการอ้างอิงกลับ ." ฉันคิดว่าเขารู้สึกแบบเดียวกันกับเครื่องหมายบวกดังนั้นจึงจำเป็นต้องหลบหนีเพื่อใช้มันเป็นตัวบ่งชี้ มันง่ายที่จะรับสิ่งนี้

ใน sed คุณจะต้องหลบหนี+, ?, |, และ( )หรือใช้ -r เพื่อใช้การขยายเพิ่มเติม (จากนั้นดูเหมือนsed -r -e "s/[[:space:]]\+/ /g"หรือsed -re "s/[[:space:]]\+/ /g"


สิ่งนี้จะลบแท็บด้วยหรือไม่ คุณช่วยอธิบายได้ไหมว่าทำไมคุณถึงใช้\+แทนที่จะเป็นแค่+?
Zulakis

โอเคฉันเข้าใจแล้ว [[: space:]] เท่ากับ [\ t \ r \ n \ v \ f] แต่คุณช่วยอธิบายได้ไหมว่าทำไมคุณถึงต้องใช้งาน\+
Zulakis

3
[[: space:]] เทียบเท่ากับ '\ s' ดังนั้นเวอร์ชันที่สั้นกว่าคือ "s / \ s \ + / / g"
3molo

2
การแสดงออกปกติพื้นฐานใช้เครื่องหมายทับขวาก่อนที่จะมีเครื่องหมายบวกเมื่อใช้หมายถึง“หนึ่งหรือมากกว่าของตัวอักษรก่อนหน้าหรือกลุ่ม” แหล่งdeveloper.apple.com/library/mac/#documentation/opensource/...
3molo

อ่าเข้าใจแล้ว! ฉันไม่ทราบว่ามีเวอร์ชัน regex แตกต่างกัน ขอบคุณ
Zulakis

6

คุณสามารถใช้-sตัวเลือก ("บีบ") ของtr:

$ tr -s '[:blank:]' <<< 'test.de.          1547    IN      SOA     ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600'
test.de. 1547 IN SOA ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600

[:blank:]ตัวละครคลาสประกอบด้วยช่องว่างและแท็บ


-2

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

alias ll='ls -lh | sed "s/ \+/ /g" | cut -f5,9 -d" " | sed "s/ /\t/g"'

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