따라서 일반적으로 저는 텍스트 처리(특히 대용량 파일의 경우)를 찾는 경향이 sed
있으며 일반적으로 셸 자체에서 이러한 작업을 수행하는 것을 피합니다.
그러나 나는 이것이 바뀔 수 있다고 생각합니다. 나는 이리저리 살펴 man ksh
보다가 이것을 발견했습니다.
<#pattern Seeks forward to the beginning of the
next line containing pattern.
<##pattern The same as <# except that the por‐
tion of the file that is skipped is
copied to standard output.
실제 실용성에 회의적이어서 한번 시도해 보기로 결정했습니다. 나는 그랬다:
seq -s'foo bar
' 1000000 >file
...다음과 같은 백만 행의 데이터에 대해:
1foo bar
...
999999foo bar
1000000
...그리고 sed
다음과 비교해보세요:
p='^[^0-8]99999.*bar'
for c in "sed '/$p/q'" "ksh -c ':<##@(~(E)$p)'"
do </tmp/file eval "time ( $c )"
done | wc -l
따라서 두 명령 모두 달성해야 합니다.999999푸바이렇게 하려면 패턴 일치 구현에서 최소한 각 줄의 시작과 끝을 평가해야 합니다. 또한 음수 패턴에 대해 첫 번째 문자의 유효성을 검사해야 합니다. 간단한 일이지만... 결과는 내가 기대했던 것과 다릅니다.
( sed '/^[^0-8]99999.*bar/q' ) \
0.40s user 0.01s system 99% cpu 0.419 total
( ksh -c ':<##@(~(E)^[^0-8]99999.*bar)' ) \
0.02s user 0.01s system 91% cpu 0.033 total
1999997
ksh
여기서는 ERE와 sed
BRE가 사용됩니다. 이전에 쉘 모드로 동일한 작업을 수행했지만 ksh
결과는 다르지 않았습니다.
ksh
그럼에도 불구하고, 이는 10배가 넘는 매우 중요한 차이입니다 sed
. 이전에 David Korn이 자신의 io lib를 작성하고 이를 구현했다는 내용을 읽은 적이 있습니다 ksh
. 관련이 있을 수 있습니까? - 하지만 나는 그것에 대해 거의 아무것도 모릅니다. 쉘은 왜 그렇게 잘 작동합니까?
나에게 더욱 놀라운 점은 ksh
사용자가 요청한 위치에 오프셋을 남겨둔다는 것입니다. 얻기 위해(거의)또한(암소 비슷한 일종의 영양) sed
당신은 사용해야합니다 -u
-아주 느린.
다음은 grep
v. ksh
테스트입니다.
1000000 #grep + head
( grep -qm1 '^[^0-8]99999.*bar'; head -n1; ) \
0.02s user 0.00s system 90% cpu 0.026 total
999999foo bar #ksh + head
( ksh -c ':<#@(~(E)^[^0-8]99999.*bar)'; head -n1; ) \
0.02s user 0.00s system 73% cpu 0.023 total
ksh
여기서 비트는 grep
- 항상 그런 것은 아니지만 - 거의 밀접하게 연결되어 있습니다. 하지만 여전히 훌륭해요그리고 ksh
head
미리보기 시작을 위한 입력 제공앞으로일치합니다.
사실이라고 하기엔 너무 좋은 것 같다고 생각했어요. 이러한 명령은 뒤에서 무엇을 다르게 수행합니까?
아, 그리고 여기에는 서브쉘도 없는 것 같습니다.
ksh -c 'printf %.5s "${<file;}"'
답변1
ksh는 다음을 사용하는 것뿐만 아니라SFIO그러나 자체 사용자 정의 메모리 할당자를 사용합니다.
그래도 내 생각에는 sfio가 이 경우에 차이를 만든다는 것입니다. 방금 strace에서 예제를 실행해 보았는데 ksh가 약 200회(65KB 블록) 읽기/쓰기를 호출하고 sed가 약 3400회(4KB 블록) 읽기/쓰기를 호출하는 것을 볼 수 있습니다. sed -u를 사용하면 내 노트북이 거의 녹아서 읽기는 바이트 단위로, 쓰기는 라인 단위로 이루어집니다. Ksh는 단순히 lseek를 사용합니다. Grep은 약 400개의 읽기(32KB 블록)를 사용합니다.