จะเปลี่ยนเครื่องหมายคำพูดในไฟล์ด้วย sed ได้อย่างไร?


10

ฉันมีไฟล์ที่มี xml หลายบรรทัด ฉันต้องการแทนที่บางส่วนของไฟล์ บางส่วนของไฟล์มีเครื่องหมายอัญประกาศ ( ") ซึ่งฉันต้องการแทนที่ ฉันพยายามหลีกเลี่ยงเครื่องหมายคำพูดด้วย\แต่ฉันไม่คิดว่ามันจะทำงานได้ตามผลลัพธ์ของไฟล์ของฉัน

นี่คือตัวอย่างของคำสั่ง sed ของฉัน:

sed -e "s/\"text\"/'text'/ig" file.xml > temp.tmp

นี่เป็นวิธีที่คุณหลีกเลี่ยงเครื่องหมายคำพูดในคำสั่ง sed หรือฉันกำลังทำอะไรผิดหรือเปล่า?


2
คำสั่งของคุณมีลักษณะที่เหมาะสมสำหรับการแทนที่ด้วย"text" 'text'แน่นอนว่ามันจะไม่ทำอะไร"othertext"เลย แสดงบรรทัดอินพุตสองสามบรรทัดเอาต์พุตที่ไม่ต้องการที่สอดคล้องกันและอธิบายเอาต์พุตที่คุณต้องการแทน
Gilles 'หยุดความชั่วร้าย'

ดังนั้น\"วิธีที่ถูกต้องในการหนีเครื่องหมายคำพูดในคำสั่ง sed คืออะไร?
jbranchaud

4
ไม่ได้สำหรับ sed: sed "ไม่จำเป็นหรือสนับสนุนการหลบหนี แต่คำสั่งเชลล์ของคุณใช้สตริงที่มีเครื่องหมายคำพูดคู่และ\"ถูกต้องที่นั่น sedโปรแกรมเห็นเป็นอาร์กิวเมนต์ไปs/"text"/'text'/ig -e
Gilles 'หยุดความชั่วร้าย'

@Gilles เกี่ยวกับช่องว่าง? sed เข้าใจและเคารพในพื้นที่สีขาวหรือไม่? ตัวอย่างเช่นหากคำสั่งของฉันมีอยู่s/\"text\" /'text'/igจะพบเฉพาะ"text" กับพื้นที่หลังจากนั้น
jbranchaud

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

คำตอบ:


11

สองเคล็ดลับ:

  1. คุณไม่สามารถยกเว้นเครื่องหมายคำพูดเดี่ยวภายในสตริงที่มีเครื่องหมายคำพูดเดี่ยว ดังนั้นคุณต้องปิดคำพูดเพิ่มคำพูดที่หลบหนีจากนั้นเปิดคำพูดอีกครั้ง นั่นคือ: 'foo'\''bar'ซึ่งแบ่งออกเป็น:

    • 'foo'        ที่ยกมา foo
    • \'             หนี '
    • 'bar'        ที่ยกมา bar

    foo'barยอมให้

  2. (ไม่บังคับ) คุณไม่จำเป็นต้องใช้/ในโหมด sed ฉันพบว่าการใช้/และ\ในการแสดงออกที่เหมือนกันทำให้ยากต่อการอ่าน

ตัวอย่างเช่นหากต้องการลบเครื่องหมายคำพูดออกจากไฟล์นี้:

$ cat /tmp/f
aaa"bbb"'ccc'aaa

ด้วยสองเคล็ดลับข้างต้นคำสั่งที่คุณสามารถใช้เพื่อลบทั้งเครื่องหมายคำพูดคู่และคำเดี่ยวคือ

$ sed -e 's|["'\'']||g'  /tmp/f

จากคำแนะนำแรกของฉันเชลล์ลดอาร์กิวเมนต์ที่สองของ sed (เช่นสตริงหลัง-e) ไปที่s|["']||gและส่งผ่านสตริงนั้นไปยัง sed ขึ้นอยู่กับเคล็ดลับที่สองของฉัน sed s/['"]//gถือว่านี้เช่นเดียวกับ มันหมายถึง

ลบอักขระทั้งหมดที่ตรงกัน'หรือ"   (เช่นแทนที่ด้วยไม่มีอะไร)

คุณอาจต้องการบางสิ่งที่ซับซ้อนกว่านี้เพื่อทำสิ่งที่คุณต้องการ แต่เป็นการเริ่มต้น


1
ในการวางจุดที่ละเอียดกว่าบนเคล็ดลับที่สองของคุณ: คุณสามารถใช้อักขระใด ๆ แทน / เมื่อใช้คำสั่ง s และ y เมื่อใช้ regexps กับคำสั่ง sed อื่น ๆ ตัวคั่นแรก (หากใช้ทางเลือกในการ /) ต้องถูกหลีกหนี ตัวคั่นที่คุณต้องการจะต้องถูกหลีกเลี่ยงหากคุณพยายามจับคู่ภายใน regexp
Eli Heady

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

1

ฉันมียูทิลิตี้ยูนิกซ์พอร์ต Windows เพื่อให้คำสั่งดูแตกต่างออกไปเล็กน้อย แต่ฉันมีไฟล์ csv พร้อมเครื่องหมายจุลภาคและเครื่องหมายคำพูด ใช้หัวข้อนี้เป็นแนวทางฉันสามารถลบอัญประกาศผ่านคำสั่งนี้:

c:\Temp> cat report.csv | sed "s/\,/\ /g" | sed "s/[""]//g"

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