Nie jestem pewien, czy jest to lepsze niż robienie tego w pamięci, ale z tym, sedktóry roddziela swój infile dla każdej linii w swoim infile i innym po drugiej stronie potoku na przemian ze Hstarą przestrzenią z liniami wejściowymi ...
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'
WYNIK
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
Zrobiłem to w inny sposób. Przechowuje niektóre elementy w pamięci - przechowuje ciąg taki jak:
"$1" -
... dla każdej linii w pliku.
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"
}
To jest bardzo szybkie. Jest catto plik tyle razy, ile jest linii w pliku do |pipe. Po drugiej stronie potoku dane wejściowe są scalane z samym plikiem tyle razy, ile jest linii w pliku.
caseRzeczy jest właśnie dla przenośności - yashi zshzarówno dodatek jeden element do rozłamu, podczas mkshi poshzarówno stracić. ksh, dash, busybox, I bashwszystko podzielonego się dokładnie tak, jak wielu dziedzinach jak istnieją zera podany przez printf. Jak napisano powyżej, renderuje takie same wyniki dla każdej z wyżej wymienionych powłok na moim komputerze.
Jeśli plik jest bardzo długi, mogą występować $ARGMAXproblemy ze zbyt dużą liczbą argumentów, w którym to przypadku należy wprowadzić xargslub podobne.
Biorąc pod uwagę to samo wejście, którego użyłem przed wyjściem jest identyczne. Ale gdybym miał zwiększyć ...
seq 10 10 10000 | nl -s, >/tmp/tmp
To generuje plik prawie identyczny z tym, którego użyłem wcześniej (bez wiersza) - ale w 1000 linii. Możesz sam przekonać się, jak szybko to jest:
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
Przy 1000 liniach występuje niewielka różnica w wydajności między powłokami - bashjest niezmiennie najwolniejsza - ale ponieważ jedyną pracą, którą wykonują, jest generowanie ciągu arg (1000 kopii filename -), efekt jest minimalny. Różnica w wydajności między zsh- jak wyżej - i bashwynosi tutaj setną sekundy.
Oto kolejna wersja, która powinna działać dla pliku o dowolnej długości:
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"
)
Tworzy miękkie łącze do pierwszego argumentu /tmpz pół losową nazwą, aby nie rozłączać się z dziwnymi nazwami plików. To ważne, ponieważ catargony są podawane do niego za pośrednictwem rury za pośrednictwem xargs. cat„s wyjście jest zapisywany <&3podczas sed prints każdy wiersz w pierwszej arg tyle razy, ile jest linii w tym pliku - a jej scenariusz jest także podawany do niego rurą. Ponownie pastełączy dane wejściowe, ale tym razem wymaga tylko dwóch argumentów -dla standardowego wejścia i nazwy łącza /dev/fd/3.
To ostatnie - /dev/fd/[num]link - powinno działać na każdym systemie linux i wielu innych oprócz, ale jeśli nie tworzy nazwanego potoku mkfifoi używanie go zamiast tego powinno również działać.
Ostatnią rzeczą, jaką robi, jest rmmiękkie łącze, które tworzy przed wyjściem.
Ta wersja jest jeszcze szybsza w moim systemie. Wydaje mi się, że dzieje się tak, ponieważ chociaż uruchamia więcej aplikacji, natychmiast przekazuje im swoje argumenty - a zanim najpierw ułożył je wszystkie w stos.
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