ฉันต้องการพิมพ์บรรทัดจากไฟล์ข้างหลังโดยไม่ใช้tac
คำสั่ง มีวิธีอื่นในการทำสิ่งนั้นด้วยการทุบตี?
ฉันต้องการพิมพ์บรรทัดจากไฟล์ข้างหลังโดยไม่ใช้tac
คำสั่ง มีวิธีอื่นในการทำสิ่งนั้นด้วยการทุบตี?
คำตอบ:
ใช้sed
เพื่อเลียนแบบtac
:
sed '1!G;h;$!d' ${inputfile}
sed
หนึ่งซับที่มีชื่อเสียง ดูที่ "36. เรียงลำดับบรรทัดย้อนกลับ (เลียนแบบคำสั่ง" tac "Unix) ในเซเลบที่มีชื่อเสียงหนึ่งเดียวอธิบายสำหรับคำอธิบายที่สมบูรณ์เกี่ยวกับวิธีการทำงาน
sort
- มีโอกาสที่มันจะใช้ไฟล์ชั่วคราว)
ด้วยed
:
ed -s infile <<IN
g/^/m0
,p
q
IN
หากคุณอยู่ในBSD
/ OSX
(และหวังว่าเร็ว ๆ นี้บนGNU
/ linux
เกินไปในขณะที่มันจะเป็น POSIX ):
tail -r infile
awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' file.txt
ผ่านawk หนึ่งสมุทร
awk 'a=$0RS a{}END{printf a}'
but your first
perl reverse <> `คำตอบที่ดีที่สุด / เร็วที่สุดในหน้าเว็บ (ถึงฉัน) เร็วกว่าawk
คำตอบนี้ถึง 10 เท่า(ผู้สังเกตการณ์ที่น่ากลัวทุกคนมีความเหมือนกันเวลาฉลาด)
awk '{a[NR]=$0} END {while (NR) print a[NR--]}'
ตามที่คุณขอให้ทำด้วยวิธีทุบตีนี่เป็นวิธีแก้ปัญหาที่ไม่ได้ใช้ awk, sed หรือ perl เพียงแค่ฟังก์ชั่นทุบตี:
reverse ()
{
local line
if IFS= read -r line
then
reverse
printf '%s\n' "$line"
fi
}
ผลลัพธ์ของ
echo 'a
b
c
d
' | reverse
คือ
d
c
b
a
อย่างที่คาดไว้.
แต่ระวังว่าบรรทัดจะถูกเก็บไว้ในหน่วยความจำหนึ่งบรรทัดในแต่ละครั้งที่เรียกว่าอินสแตนซ์ของฟังก์ชั่นซ้ำ ระมัดระวังด้วยไฟล์ขนาดใหญ่
คุณสามารถส่งผ่าน:
awk '{print NR" "$0}' | sort -k1 -n -r | sed 's/^[^ ]* //g'
awk
คำนำหน้าแต่ละบรรทัดที่มีจำนวนเส้นตามด้วยช่องว่าง sort
ฝืนคำสั่งของสายโดยเรียงลำดับในฟิลด์แรก (หมายเลขบรรทัด) เพื่อย้อนกลับสไตล์ที่เป็นตัวเลข และsed
แถบปิดหมายเลขบรรทัด
ตัวอย่างต่อไปนี้แสดงสิ่งนี้ในการดำเนินการ:
pax$ echo 'a
b
c
d
e
f
g
h
i
j
k
l' | awk '{print NR" "$0}' | sort -k1 -n -r | sed 's/^[^ ]* //g'
มันเอาท์พุท:
l
k
j
i
h
g
f
e
d
c
b
a
cat -n
ทำหน้าที่เหมือนawk '{print NR" "$0}'
ใน Perl:
cat <somefile> | perl -e 'while(<>) { push @a, $_; } foreach (reverse(@a)) { print; }'
perl -e 'print reverse<>'
perl -pe '$\=$_.$\}{'
)
reverse<)
เร็วมาก: ดี! แต่อันที่ "น่าเกลียดจริงๆ" นั้นช้ามากเมื่อจำนวนบรรทัดเพิ่มขึ้น !! ....
-n
ฟุ่มเฟือยที่นั่นขอบคุณ
sort
)
วิธีการแก้ปัญหา BASH เท่านั้น
อ่านไฟล์ลงใน bash array (หนึ่งบรรทัด = หนึ่งองค์ประกอบของอาร์เรย์) และพิมพ์อาร์เรย์ในลำดับย้อนกลับ:
i=0
while read line[$i] ; do
i=$(($i+1))
done < FILE
for (( i=${#line[@]}-1 ; i>=0 ; i-- )) ; do
echo ${line[$i]}
done
while..read
ดังนั้นจริงๆเมื่อมันมาถึงการประมวลผลข้อความที่ไม่เคยใช้งาน
IFS=''
และread -r
เพื่อป้องกันการหลบหนีทุกชนิดและการกำจัด IFS ที่ตามมาไม่ให้คลาดเคลื่อน ฉันคิดว่า bash mapfile ARRAY_NAME
builtin เป็นวิธีแก้ปัญหาที่ดีกว่าสำหรับการอ่านอาร์เรย์
Bash พร้อมกับmapfile
กล่าวถึงในความคิดเห็นเพื่อ fiximan และจริง ๆ แล้วอาจเป็นรุ่นที่ดีกว่า:
# last [LINES=50]
_last_flush(){ BUF=("${BUF[@]:$(($1-LINES)):$1}"); } # flush the lines, can be slow.
last(){
local LINES="${1:-10}" BUF
((LINES)) || return 2
mapfile -C _last_flush -c $(( (LINES<5000) ? 5000 : LINES+5 )) BUF
BUF=("${BUF[@]}") # Make sure the array subscripts make sence, can be slow.
((LINES="${#BUF[@]}" > LINES ? LINES : "${#BUF[@]}"))
for ((i="${#BUF[@]}"; i>"${#BUF[@]}"-LINES; i--)); do echo -n "${BUF[i]}"; done
}
ประสิทธิภาพของมันนั้นเทียบเท่ากับsed
วิธีแก้ปัญหาและเร็วขึ้นเมื่อจำนวนบรรทัดที่ร้องขอลดลง
Simple do this with your file to sort the data in reverse order, and it should be unique.
sed -n '1h; 1d; G; h; $ p'
ตามที่ปรากฏที่นี่:
echo 'e
> f
> a
> c
> ' | nl | sort -nr | sed -r 's/^ *[0-9]+\t//'
ผล:
c a f e
awk '{print NR" "$0}' | sort -nr