Bash: วิธีรับบางบรรทัดจากไฟล์และบันทึกเอาต์พุตไปยังไฟล์อื่น [ปิด]
ฉันมีไฟล์บันทึกแบบนี้
$ cat build.log
..........
[ 60% 60917/101076] AAPT2 compile ....
[ 60% 60918/101076] AAPT2 compile ....
[ 60% 60919/101076] AAPT2 compile ....
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
#### failed to build some targets (17:26 (mm:ss)) ####
วิธีสร้างเหมือนบันทึกที่แยกวิเคราะห์ใหม่ดังนั้นผลลัพธ์ของบันทึกไฟล์ใหม่จึงเป็นดังนี้:
$ cat parsed.log
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
#### failed to build some targets (17:26 (mm:ss)) ####
เช่นเดียวกับรับความคืบหน้าสุดท้าย[ 60% 60920/101076]
จนถึงจุดสิ้นสุดของไฟล์โดยใช้ grep, sed หรืออะไรก็ได้ ขอขอบคุณ
คำตอบ
นี่คือ perl:
$ perl -0777 -lne 'print $1 if /(^\[[^[]*\z)/m' file
หรือท่อ perl:
$ perl -E 'say reverse <>' file | perl -lpE 'if (/^\[/){ say; last}' | perl -E 'say reverse <>'
สำหรับสิ่งที่awk
คุณสามารถทำได้:
$ awk 'BEGIN{RS="\\["}END{print "[" $0}' file
แน่นอนคุณอาจรู้ว่าหากความล้มเหลวเป็น 3 บรรทัดเสมอวิธีที่ง่ายที่สุดคือใช้tail
:
$ tail -n 3 file
พิมพ์ทั้งหมด:
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
$ cat build.log ........ [ 60% 60917/101076] AAPT2 compile .... [ 60% 60918/101076] AAPT2 compile .... [ 60% 60919/101076] AAPT2 compile .... [ 60% 60920/101076] AAPT2 compile .... ninja: build stopped: subcommand failed. 21:41:22 ninja failed with: exit status 1 $ awk '$2 != n[2]{print p} {p = $0; split(p,n,FS)} END{print p}' build.log
........
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
awk
เป็นเครื่องมือที่เหมาะสมสำหรับสิ่งนี้ ที่นี่เราตรวจสอบว่าฟิลด์ที่ 2 ตรงกับฟิลด์ที่ 2 ของบรรทัดก่อนหน้าหรือไม่และทำการพิมพ์หรือไม่ จากนั้นเก็บบรรทัดก่อนหน้าและทำซ้ำ พิมพ์บรรทัดสุดท้ายของอินพุตเสมอ
สิ่งนี้อาจได้ผลสำหรับคุณ (GNU sed):
sed '/^\[/h;//!H;$!d;x' file
หากเส้นเริ่มต้นให้[
จัดเก็บไว้ในช่องว่าง (เขียนทับสิ่งที่ก่อนหน้านี้)
ในทำนองเดียวกันต่อท้ายบรรทัดปัจจุบันเข้ากับช่องว่าง
ลบทุกบรรทัดยกเว้นบรรทัดสุดท้าย
ในตอนท้ายของไฟล์ให้สลับไปที่ช่องว่างและพิมพ์เนื้อหา
บางครั้งคุณอาจไม่โชคดีถ้าคุณต้องการใช้ตัวกรองประเภทนี้โดยไม่ต้องเปลี่ยนลำดับของบรรทัด และถ้าเส้นที่ไม่ได้เขียนที่จุดเริ่มต้นของไฟล์ของคุณหรือที่สิ้นสุด: tac
, sort
และuniq
จะไม่เป็นเครื่องมือที่เหมาะสม
นี่คือวิธีแก้ปัญหาโดยใช้awk
:
$ awk 'function push(a,e) { a[length(a)+1] = e } BEGIN {split("", lines); to_replace="toreplace"; exists=0} {if ($0 ~ "^\\[ [0-9]+%"){ll=$0; if (exists <= 0) {exists++; push(lines,to_replace)}} else {push(lines, $0)}} END {for (e in lines){if (lines[e] == to_replace) {print ll} else {print lines[e]}}}' test.log
..........
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
#### failed to build some targets (17:26 (mm:ss)) ####
เวอร์ชันที่อ่านได้และอธิบายได้:
# a function to append an element to an array dynamically
function push(a,e) {
a[length(a)+1] = e
}
BEGIN {
split("", lines); # initializing an array
to_replace="toreplace"; # you can change the replace key if you want
exists=0
}
{
if ($0 ~ "^\\[ [0-9]+%"){ # matching all percentages/progression lines, regardless of their values ll=$0;
if (exists <= 0) {
exists++;
push(lines, to_replace)
}
} else {
push(lines, $0)
}
}
END {
for (e in lines) {
if (lines[e] == to_replace) {
print ll
} else {
print lines[e]
}
}
}
ความแตกต่างกับโซลูชันของWilliam Purselคือเมื่อเปอร์เซ็นต์ของคุณเพิ่มขึ้น มาดูความแตกต่างของพฤติกรรมในกรณีนี้:
$ cat test.log
..........
[ 60% 60917/101076] AAPT2 compile ....
[ 60% 60918/101076] AAPT2 compile ....
[ 60% 60919/101076] AAPT2 compile ....
[ 61% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
#### failed to build some targets (17:26 (mm:ss)) ####
$ awk 'function push(a,e) { a[length(a)+1] = e } BEGIN {split("", lines); to_replace="toreplace"; exists=0} {if ($0 ~ "^\\[ [0-9]+%"){ll=$0; if (exists <= 0) {exists++; push(lines,to_replace)}} else {push(lines, $0)}} END {for (e in lines){if (lines[e] == to_replace) {print ll} else {print lines[e]}}}' test.log
..........
[ 61% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
#### failed to build some targets (17:26 (mm:ss)) ####
$ awk '$2 != n[2]{print p} {p = $0; split(p,n,FS)} END{print p}' test.log
..........
[ 60% 60919/101076] AAPT2 compile ....
[ 61% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
#### failed to build some targets (17:26 (mm:ss)) ####
ดังนั้นคุณอาจจะเลือกว่าคุณต้องการเก็บเส้นความก้าวหน้าสุดท้ายไว้แม้ว่าเปอร์เซ็นต์จะไม่เท่ากันหรือถ้าคุณต้องการกรองเฉพาะบรรทัดที่มีเปอร์เซ็นต์เท่ากันหลาย ๆ ครั้ง
หากมีการรับประกันว่าบรรทัดแรกที่คุณต้องการนำออกเป็นบรรทัดสุดท้ายที่ขึ้นต้นด้วย[
คุณสามารถทำได้ซึ่งจะแทนที่ทุกอย่างตั้งแต่ต้นไฟล์ไปจนถึง[
บรรทัดสุดท้ายที่นำหน้าด้วยบรรทัดเดียว[
:
sed -z 's/.*\n\[/[/' file
สมมติว่า...
บรรทัดที่จุดเริ่มต้นของการป้อนข้อมูลตัวอย่างของคุณแสดงถึง[...] ...
บรรทัดที่นำหน้ามากกว่า:
$ awk '/^\[/{p=$0 ORS; next} {print p $0; p=""}' build.log
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
#### failed to build some targets (17:26 (mm:ss)) ####
หากสมมติฐานนั้นไม่ถูกต้องโปรดแก้ไขคำถามของคุณเพื่อแสดงตัวอย่างขั้นต่ำที่สมบูรณ์และตรวจสอบได้ซึ่งเป็นตัวอย่างที่มีค่าตัวแทนเท่านั้นไม่ใช่...
s