การใช้ sed รับซับสตริงระหว่างเครื่องหมายคำพูดคู่สองตัว


14

ฉันมีไฟล์

xyz... rsync: "/home/path/to/file": Permission denied (13) rsync:
"/home/path/to/file1": Permission denied (13) rsync:
"/home/path/to/file2": Permission denied (13) rsync:
"/home/path/to/file3": Permission denied (13)

ตอนนี้ฉันต้องการแยกพา ธ ของไฟล์เท่านั้นและเก็บไว้ในไฟล์อื่น ไฟล์ที่ส่งออกเป็นเช่น:

/home/path/to/file 
/home/path/to/file1 
/home/path/to/file2
/home/path/to/file3

ใช้ sed หรือ awk ฉันจะทำสิ่งนี้ได้อย่างไร

ฉันได้ลองแล้วsed -n '/"/,/"/p' myfileแต่มันไม่ทำงาน


3
สำหรับผู้ที่ลงคะแนนให้ปิด - สิ่งนี้จะเป็นหัวข้อนอกได้อย่างไร? มันเกี่ยวกับการเขียนโปรแกรมเชลล์ !! นั่นคือการเขียนโปรแกรมซึ่งเป็นหัวข้อสำหรับกองล้น!
Jonathan Leffler

2
ยินดีต้อนรับสู่ Stack Overflow อย่างที่คุณเห็นบางครั้งเรามีปัญหากับคนที่มีอาการคันเมื่อนิ้วมือปิดคำถามที่ดีอย่างสมบูรณ์ (เช่นนี้) ด้วยเหตุผลที่ไม่ดีสำหรับการปิด มันไม่ได้เกิดขึ้นทั้งหมดที่เกิดขึ้นบ่อยครั้ง (หรือฉันไม่ได้เห็นปัญหาในเวลาที่เกิดขึ้นทั้งหมด) แต่มันเกิดขึ้น อย่าลืมอ่านคำถามที่พบบ่อยก่อนที่จะยาวเกินไป
Jonathan Leffler

คำตอบ:


17

คุณสามารถไพพ์ stderr ของคำสั่ง rsync ของคุณไปยังสคริปต์ awk:

awk -F '"' '{print $2}' 

หรือคำสั่งตัดแบบนี้:

cut -d'"' -f2

2
หรือสั้นกว่า:cut -d\" -f2

@AndersJohansson: ขอบคุณฉันเพิ่มคำสั่งตัดของคุณเพื่อตอบเช่นกัน
anubhava

ฉันคิดว่านี่จะไม่ทำงาน .. เพราะคุณสามารถดูหมายเลขฟิลด์ของไฟล์พา ธ ไม่คงที่ $ 2 หรือ f2 .. ขอบคุณ!

จริงๆแล้ว rsync จะเขียน filepath ก่อนระหว่าง"และ"บน stderr
anubhava

1
@ Jam88: อันที่จริงมันจะทำงานได้เพราะวิธีที่ anubbhava เขียน ตัวคั่นฟิลด์ถูกตั้งค่าเป็นเครื่องหมายคำพูดคู่ นั่นหมายความว่าทุกอย่างขึ้นอยู่กับราคาคู่แรก (อาจจะเป็นสตริงว่าง) เป็น$1; ทุกอย่างระหว่างเครื่องหมายคำพูดคู่แรกและตัวที่สองคือ$2; และทุกอย่างหลังจากเครื่องหมายคำพูดคู่ที่สองอยู่ใน$3( $4, ... ) ชื่อไฟล์คือ (เห็นได้ชัด) เสมอระหว่างเครื่องหมายคำพูดสองครั้งแรกเสมอดังนั้นโซลูชันนี้ควรใช้งานได้ (และทำเมื่อฉันทดสอบ)
Jonathan Leffler

6

การใช้sed:

sed 's/^[^"]*"\([^"]*\)".*/\1/'

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

$ sed 's/^[^"]*"\([^"]*\)".*/\1/' <<'EOF'
> xyz... rsync: "/home/path/to/file": Permission denied (13) rsync:
> "/home/path/to/file1": Permission denied (13) rsync:
> "/home/path/to/file2": Permission denied (13) rsync:
> "/home/path/to/file3": Permission denied (13)
> EOF
/home/path/to/file
/home/path/to/file1
/home/path/to/file2
/home/path/to/file3
$

ทดสอบ RHEL 5 Linux กับ GNU sedแต่ใช้คุณสมบัติที่จะได้ทำงานในรุ่นที่ 7 sedยูนิกซ์™รุ่น

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

sed 's/^[^"]*"//; s/".*//'

อนึ่งคำสั่งที่คุณลอง (`sed -n '/" /, / "/ p') พิมพ์จากบรรทัดหนึ่งที่มีเครื่องหมายคำพูดคู่ไปยังบรรทัดถัดไปที่มีเครื่องหมายคำพูดคู่โดยไม่ต้องแก้ไขบรรทัดเลย ซึ่งเป็นเหตุผลว่าทำไมมันถึงไม่เหมาะกับคุณ - ทำในสิ่งที่คุณถาม แต่สิ่งที่คุณขอให้ทำไม่ใช่สิ่งที่คุณตั้งใจจะขอให้ทำ

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


1

หากเวอร์ชันของคุณgrepรองรับ Perl-regexp:

grep -oP '(?<=")/home/.*?(?=")' file >> anotherfile

ผล:

/home/path/to/file
/home/path/to/file1
/home/path/to/file2
/home/path/to/file3

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

grep -oP '(?<=")[^"]*' file >> anotherfile

คุณจำเป็นต้องทำที่.*ไม่โลภด้วย.*?ในกรณีที่มีการเสนอราคาสองครั้งต่อมาในบรรทัด? หรือใช้[^"]*แทน.*?
Jonathan Leffler

-1

ใช้โอเปอเรเตอร์ >> เพื่อบันทึกเอาต์พุตใด ๆ ลงในไฟล์

ชอบ

grep -r "pattern" * >> file.txt

ดังนั้นเพียงแค่เปลี่ยนสถานการณ์สมมติของคุณโดยใช้ sed โดยต่อท้าย

>> filename

เพื่อคำสั่ง


การgrep -rค้นหาแบบเรียกซ้ำผ่านไดเรกทอรีใด ๆ ที่ระบุไว้ในอาร์กิวเมนต์ ( *) มันไม่ชัดเจนว่าคุณมีรูปแบบใดในใจ แต่grepจะรับทั้งสาย จุดประสงค์ของการฝึกคือการรวบรวมข้อมูลจากส่วนหนึ่งของบรรทัด หากคุณกำลังใช้ GNU grepมีวิธีการทำเช่นนั้น ( -o); สิ่งเหล่านี้ไม่ใช่แบบมาตรฐาน (ยกเว้นในขอบเขตที่ GNU กำหนดมาตรฐานแบบพฤตินัย) ในทำนองเดียวกันกับการใช้ PCRE นิพจน์ปกติ นี่คือส่วนขยาย GNU อื่น พวกมันใช้ได้ถ้าคุณมี GNU grepและไม่มีแผนที่จะทำงานบนแพลตฟอร์มที่ GNU grepไม่พร้อมใช้งานตามค่าเริ่มต้น
Jonathan Leffler

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