ผมไม่แน่ใจว่านี้จะดีกว่าที่จะทำมันในความทรงจำ แต่ด้วยความsed
ที่r
EADS ออก INFILE สำหรับทุกบรรทัดใน INFILE และอื่นในด้านอื่น ๆ ของท่อสลับH
พื้นที่เก่าที่มีเส้นที่นำเข้า ...
cat <<\IN >/tmp/tmp
Row1,10
Row2,20
Row3,30
Row4,40
IN
</tmp/tmp sed -e 'i\
' -e 'r /tmp/tmp' |
sed -n '/./!n;h;N;/\n$/D;G;s/\n/ /;P;D'
เอาท์พุท
Row1,10 Row1,10
Row1,10 Row2,20
Row1,10 Row3,30
Row1,10 Row4,40
Row2,20 Row1,10
Row2,20 Row2,20
Row2,20 Row3,30
Row2,20 Row4,40
Row3,30 Row1,10
Row3,30 Row2,20
Row3,30 Row3,30
Row3,30 Row4,40
Row4,40 Row1,10
Row4,40 Row2,20
Row4,40 Row3,30
Row4,40 Row4,40
ฉันทำอย่างนี้อีกทาง มันจะเก็บบางส่วนในหน่วยความจำ - จะเก็บสตริงเช่น:
"$1" -
... สำหรับแต่ละบรรทัดในไฟล์
pairs(){ [ -e "$1" ] || return
set -- "$1" "$(IFS=0 n=
case "${0%sh*}" in (ya|*s) n=-1;; (mk|po) n=+1;;esac
printf '"$1" - %s' $(printf "%.$(($(wc -l <"$1")$n))d" 0))"
eval "cat -- $2 </dev/null | paste -d ' \n' -- $2"
}
มันเร็วมาก มันเป็นไฟล์หลายครั้งตามที่มีเส้นในไฟล์ไปยังcat
|pipe
อีกด้านหนึ่งของไปป์ที่อินพุตถูกรวมเข้ากับไฟล์ตัวเองหลาย ๆ ครั้งตามที่มีบรรทัดในไฟล์
case
สิ่งที่เป็นเพียงสำหรับการพกพา - yash
และzsh
ทั้งสององค์ประกอบหนึ่งเพิ่มการแยกในขณะที่mksh
และposh
ทั้งสูญเสียหนึ่ง ksh
, dash
, busybox
และแยกออกทั้งหมดไปยังเขตว่ามากที่สุดเท่าที่มีเลขศูนย์เป็นพิมพ์โดยbash
printf
ตามที่เขียนไว้ข้างต้นทำให้ผลลัพธ์เหมือนกันสำหรับทุกเชลล์ที่กล่าวถึงข้างต้นบนเครื่องของฉัน
หากไฟล์มีความยาวมากอาจมี$ARGMAX
ปัญหากับอาร์กิวเมนต์ที่มากเกินไปซึ่งในกรณีนี้คุณจะต้องแนะนำxargs
หรือคล้ายกันเช่นกัน
รับอินพุตเดียวกันกับที่ฉันใช้ก่อนที่เอาต์พุตจะเหมือนกัน แต่ถ้าฉันจะใหญ่ขึ้น ...
seq 10 10 10000 | nl -s, >/tmp/tmp
ที่สร้างไฟล์เกือบจะเหมือนกับสิ่งที่ฉันใช้มาก่อน(sans 'Row') - แต่ที่ 1,000 บรรทัด คุณสามารถเห็นตัวเองว่ามันเร็วแค่ไหน:
time pairs /tmp/tmp |wc -l
1000000
pairs /tmp/tmp 0.20s user 0.07s system 110% cpu 0.239 total
wc -l 0.05s user 0.03s system 32% cpu 0.238 total
ที่ 1,000 บรรทัดมีการเปลี่ยนแปลงเล็กน้อยในประสิทธิภาพระหว่างเชลล์ - bash
ช้าที่สุด - แต่เนื่องจากงานเดียวที่พวกเขาทำต่อไปคือการสร้างสตริง arg (1,000 สำเนาfilename -
)ผลที่ได้คือน้อยที่สุด ความแตกต่างของประสิทธิภาพระหว่างzsh
- ดังกล่าวข้างต้น - และbash
อยู่ที่ 100 ของวินาทีที่นี่
นี่เป็นอีกเวอร์ชั่นที่ควรใช้กับไฟล์ที่มีความยาวเท่าใด:
pairs2()( [ -e "$1" ] || exit
rpt() until [ "$((n+=1))" -gt "$1" ]
do printf %s\\n "$2"
done
[ -n "${1##*/*}" ] || cd -P -- "${1%/*}" || exit
: & set -- "$1" "/tmp/pairs$!.ln" "$(wc -l <"$1")"
ln -s "$PWD/${1##*/}" "$2" || exit
n=0 rpt "$3" "$2" | xargs cat | { exec 3<&0
n=0 rpt "$3" p | sed -nf - "$2" | paste - /dev/fd/3
}; rm "$2"
)
มันสร้างซอฟต์ลิงค์ไปยัง arg แรกของมัน/tmp
ด้วยชื่อแบบกึ่งสุ่มเพื่อที่จะได้ไม่ถูกแขวนบนชื่อไฟล์แปลก ๆ นั่นเป็นสิ่งสำคัญเพราะcat
's args xargs
จะเลี้ยงมันมากกว่าท่อผ่าน cat
เอาต์พุตของจะถูกบันทึก<&3
ในขณะที่sed
p
rints ทุกบรรทัดใน ARG แรกหลาย ๆ ครั้งตามที่มีบรรทัดในไฟล์นั้น - และสคริปต์จะถูกป้อนไปยังผ่านทางไพพ์ อีกครั้งpaste
ผสานการป้อนข้อมูลของตน แต่เวลานี้มันใช้เวลาเพียงสองข้อโต้แย้งอีกครั้งสำหรับการป้อนข้อมูลมาตรฐานและชื่อการเชื่อมโยง-
/dev/fd/3
สุดท้าย - /dev/fd/[num]
ลิงก์ - ควรทำงานกับระบบ linux ใด ๆ และอื่น ๆ อีกมากมาย แต่ถ้ามันไม่ได้สร้างไปป์ที่มีชื่อด้วยmkfifo
และใช้มันแทนที่จะทำงานได้ดี
สิ่งสุดท้ายที่มันทำคือrm
soft-link ที่สร้างขึ้นก่อนออก
เวอร์ชันนี้ยังเร็วกว่าในระบบของฉัน ฉันเดาว่าเป็นเพราะถึงแม้ว่ามันจะประมวลผลแอพพลิเคชั่นได้มากขึ้นมันก็เริ่มส่งข้อโต้แย้งของพวกเขาทันที - ก่อนที่มันจะซ้อนพวกมันทั้งหมดก่อน
time pairs2 /tmp/tmp | wc -l
1000000
pairs2 /tmp/tmp 0.30s user 0.09s system 178% cpu 0.218 total
wc -l 0.03s user 0.02s system 26% cpu 0.218 total