스트림의 처음 N바이트를 효율적으로 건너뜁니다.

스트림의 처음 N바이트를 효율적으로 건너뜁니다.

을 사용하는 것을 알고 있지만 tail -c +N매우 느리고 하나의 CPU 코어를 고정합니다.

 leijurvs-MacBook-Pro:Downloads leijurv$ time cat /dev/zero | head -c 100000000 | shasum -a 256
a993f8c574e0fea8c1cdcbcd9408d9e2e107ee6e4d120edcfa11decd53fa0cae  -
cat /dev/zero  0.00s user 0.02s system 4% cpu 0.471 total
head -c 100000000  0.01s user 0.03s system 9% cpu 0.470 total
shasum -a 256  0.45s user 0.02s system 99% cpu 0.469 total
 leijurvs-MacBook-Pro:Downloads leijurv$ time cat /dev/zero | head -c 100000000 | tail -c +2 | shasum -a 256
f4be792b71a024a60d77b3ac4c1c2b88ac51480fa25f88d10865827f8c086506  -
cat /dev/zero  0.01s user 0.03s system 0% cpu 7.241 total
head -c 100000000  0.02s user 0.03s system 0% cpu 7.240 total
tail -c +2  7.20s user 0.03s system 99% cpu 7.247 total
shasum -a 256  0.51s user 0.04s system 7% cpu 7.247 total
 leijurvs-MacBook-Pro:Downloads leijurv$ 

head매우 좋은. 나는 shasum을 사용하여 처음 100MB에 대해 0을 얻었습니다 head. 0.47초가 걸렸습니다.

tail -c +2예전에는 첫 번째 바이트를 건너뛰곤 했는데 갑자기 7.2초가 걸렸습니다.

tail이 시간 동안 하나의 CPU 코어가 고정됩니다.

내가 어떻게 할 수있는표현적으로스트림의 처음 N바이트를 건너뛰시겠습니까?

답변1

파일을 입력하기 전에 파일의 첫 번째 바이트를 건너뛰려면 shasum다음을 수행할 수 있습니다( 출력 형식이 이것이 사용 중인 쉘임을 나타내기 zsh때문에 여기에 사용된 구문 ).time

time cat /dev/zero | head -c 100000000 |
   (LC_ALL=C read -u0 -k1 && shasum -a 256)

이는 추가 프로세스가 없으며 첫 번째 바이트가 파이프에서 읽혀짐을 의미합니다.read시작하기 전에 shasum.

그게 LC_ALL=C read -u0 -k1바로 reading 1문자입니다( k여기서는열쇠처음에는 read -k키 입력이 터미널에서 읽혀집니다. 여기서 문자는 LC_ALL=C파일 설명자 u니트 번호 0(stdin; 여기서는 터미널이 아닌 스트림에서 읽는다는 점을 분명히 하기 위해) 덕분에 단일 바이트입니다.

쉘을 사용하면 bash다음과 같습니다.read명령은 입니다 LC_ALL=C IFS= read -rd '' -n1.

zsh에 해당하는 것은 read -k일반적으로 이지만 read -NNUL 바이트를 포함하는 입력에는 작동하지 않으며 bash단지 read스트라이핑일 뿐입니다(또한 -Nksh93에서 복사한 것은 상대적으로 새로운 추가 항목으로 macos에 있는 고대 버전의 bash에서는 사용할 수 없습니다). 구분자를 NUL 바이트(여기서는 빈 문자열로 표시됨)로 설정 하여 d이를 방지할 수 있습니다 . 첫 번째 NUL로 구분된 레코드에서 한 문자를 읽는 것입니다 -n1(다시 바이트를 생성하여). LC_ALL=C그러나 이는 와 같은 다른 바이트 수에 적응하지 않는다는 것을 의미합니다 -rd '' -n2. 첫 번째 바이트가 0이면 바이트를 건너뜁니다.

다른 셸의 경우 read명령을 dd bs=1 count=1 > /dev/null 2>&1(change , 1바이트 이상 건너뛰지 count마세요 )로 바꿀 수 있습니다. 또한 함께 작동합니다bshead -c 1 > /dev/null일부head비표준 옵션을 지원 하지만 -c전부는 아니지만(특히 FreeBSD가 아니므로 아마도 macOS는 아닐 수도 있음) 일부는 더 적은 바이트의 출력이 요청되더라도 고정 크기 청크로 입력을 읽습니다. 그러나 위의 내용과 달리 read해당 1바이트를 읽을 수 없을 때 실패 종료 상태를 보고하지 않으므로 shasum어떤 경우에도 실행됩니다.

체크섬이 파이프 대신 일반 파일인 경우 다음을 수행할 수 있습니다.줄넘기더 효율적입니다(여러 바이트를 건너뛰어야 한다고 가정).구하다파일에서 건너뛸 부분을 읽고 삭제하는 대신(스틸 zsh구문):

zmodload zsh/system
{ sysseek 1234567 && shasum -a 256; } < some-big-file

처음 1234567바이트를 건너뜁니다.

또는 ksh93을 사용하십시오.

shasum -a 256 < some-big-file <#((1234567))

다른 껍질과일부dd(저는 macOS 구현을 모릅니다) 다음을 수행할 수 있습니다.

{ dd bs=1 skip=1234567 count=0 2> /dev/null; shasum -a 256; } < some-big-file

그러나 count=0휴대용으로 사용할 수는 없습니다. count가 0일 때 모든 dd구현이 여기에서 작업을 수행하는 것은 아닙니다. 일부에서는 이렇게 해석하기도 합니다.lseek()count=infinity

답변2

Mac OSX는 tail느립니다.

brew install coreutilsgtail그런 다음 문제 해결을 위해 전환하십시오 .

 leijurvs-MacBook-Pro:~ leijurv$ time cat /dev/zero | head -c 100000000 | tail -c +2 | shasum -a 256
f4be792b71a024a60d77b3ac4c1c2b88ac51480fa25f88d10865827f8c086506  -
cat /dev/zero  0.01s user 0.03s system 0% cpu 7.153 total
head -c 100000000  0.02s user 0.03s system 0% cpu 7.152 total
tail -c +2  7.07s user 0.03s system 99% cpu 7.159 total
shasum -a 256  0.51s user 0.06s system 7% cpu 7.154 total
 leijurvs-MacBook-Pro:~ leijurv$ time cat /dev/zero | head -c 100000000 | gtail -c +2 | shasum -a 256
f4be792b71a024a60d77b3ac4c1c2b88ac51480fa25f88d10865827f8c086506  -
cat /dev/zero  0.00s user 0.02s system 4% cpu 0.497 total
head -c 100000000  0.02s user 0.08s system 18% cpu 0.496 total
gtail -c +2  0.05s user 0.10s system 30% cpu 0.496 total
shasum -a 256  0.47s user 0.02s system 99% cpu 0.496 total
 leijurvs-MacBook-Pro:~ leijurv$ 

관련 정보