ผมไม่แน่ใจว่านี้จะดีกว่าที่จะทำมันในความทรงจำ แต่ด้วยความsedที่rEADS ออก 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 prints ทุกบรรทัดใน ARG แรกหลาย ๆ ครั้งตามที่มีบรรทัดในไฟล์นั้น - และสคริปต์จะถูกป้อนไปยังผ่านทางไพพ์ อีกครั้งpasteผสานการป้อนข้อมูลของตน แต่เวลานี้มันใช้เวลาเพียงสองข้อโต้แย้งอีกครั้งสำหรับการป้อนข้อมูลมาตรฐานและชื่อการเชื่อมโยง-/dev/fd/3
สุดท้าย - /dev/fd/[num]ลิงก์ - ควรทำงานกับระบบ linux ใด ๆ และอื่น ๆ อีกมากมาย แต่ถ้ามันไม่ได้สร้างไปป์ที่มีชื่อด้วยmkfifoและใช้มันแทนที่จะทำงานได้ดี
สิ่งสุดท้ายที่มันทำคือrmsoft-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