Bunun bellekte yapmaktan daha iyi olmadığından emin değilim, ancak dosyasındaki her satır için dolgusunu ve giriş çizgileriyle eski alanı değiştiren bir borunun diğer tarafındaki sızıntısını ortaya sed
çıkaran r
bir 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'
ÇIKTI
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
Bunu başka bir şekilde yaptım. Bu saklamak yapar bazı : Bir dize gibi saklar - bellekte
"$1" -
... dosyadaki her satır için.
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"
}
Çok hızlı. Bu cat
, dosyada satırlar olduğu kadar çok dosyadır |pipe
. Borunun diğer tarafında bu giriş, dosyada satırlar olduğu kadar dosyanın kendisi ile birleştirilir.
case
- malzeme sadece taşınabilirlik içindir yash
ve zsh
süre, bölünmeye hem eklenti bir unsuru mksh
ve posh
hem kaybetmek biri. ksh
, dash
, busybox
Ve bash
tarafından basılan olarak sıfır var gibi birçok alanda tam olarak dışarı bütün bölünmüş printf
. Yukarıda yazıldığı gibi, makinemde yukarıda belirtilen mermilerin her biri için aynı sonuçları verir.
Dosya çok uzunsa, $ARGMAX
çok fazla argümanla ilgili sorunlar olabilir , bu durumda da tanıtmanız xargs
veya benzer olmanız gerekir .
Çıktı aynı olmadan önce kullanılan aynı girdi göz önüne alındığında. Ama daha büyük olsaydım ...
seq 10 10 10000 | nl -s, >/tmp/tmp
Bu, daha önce kullandığımla neredeyse aynı olan bir dosya oluşturur (sans 'Row') - ancak 1000 satırda. Ne kadar hızlı olduğunu kendiniz görebilirsiniz:
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
1000 satırda, mermiler arasında performansta küçük bir değişiklik var - bash
her zaman en yavaş olanı - ama yine de yaptıkları tek iş, arg dizesini (1000 kopya filename -
) oluşturmak olduğu için, etki minimumdur. zsh
Yukarıdaki gibi - ve arasındaki performans farkı bash
burada saniyenin 100.'sidir.
İşte herhangi bir uzunlukta bir dosya için çalışması gereken başka bir sürüm:
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"
)
İlk argümanına /tmp
yarı rastgele bir adla yumuşak bir bağlantı oluşturur, böylece garip dosya adlarına asılmayacaktır. Bu önemlidir çünkü cat
'argümanları üzerinden bir boru üzerinden beslenir xargs
. cat
bireyin çıkış kaydedilir <&3
ise sed
p
bu dosyada hatları vardır kadar çok kez rints ilk parametre her çizgi - ve komut dosyası da bir boru aracılığı ile beslenmektedir. Yine paste
girişini birleştirir, ancak bu kez -
standart girişi ve bağlantı adı için sadece iki argüman alır /dev/fd/3
.
Bu son - /dev/fd/[num]
bağlantı - herhangi bir linux sistemi ve daha birçok şey üzerinde çalışmalıdır, ancak bununla birlikte adlandırılmış bir boru oluşturmazsa mkfifo
ve bunun yerine de kullanılmalıdır.
Yaptığı son şey, rm
çıkmadan önce oluşturduğu yumuşak bağlantıdır.
Bu sürüm aslında hala sistemimde daha hızlı . Sanırım daha fazla uygulama yürütmesine rağmen, argümanlarını derhal vermeye başlar - oysa önce hepsini istiflemeden önce.
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