md5 체크섬과 파일 이름으로 가득 찬 파일이 있습니다. 각 행에 대해 일부 처리를 수행해야 하므로 다음 사항을 알아야 합니다.
- 체크섬은 무엇입니까
- 파일 이름은 무엇입니까
그리고 적절한 조치를 취하세요. 즉, 체크섬을 변수에 넣은 다음 파일 이름을 넣어야 합니다. 파일 이름에 ASCII가 아닌 문자가 포함될 수 있지만 개행 문자를 표시하고 싶지 않습니다. 다음과 같습니다.
05c00367e8914ca1be0964821d127977 ./.fseventsd/0000000000097aa1
cd9d4291f59a43c0e3d73ff60a337bb5 ./.fseventsd/00000000000fdfec
5d1280769e741e04622cfd852f33a138 ./.fseventsd/0000000000103197
8dda3534e5bbc0be1d15db2809123c50 ./.fseventsd/000000000017c9ca
(...etc., about 100,000 lines)
전통적으로 다음과 같이 할 수 있습니다.
md5sum=$(echo $line | awk '{print $1}')
filename=$(echo $line | sed 's/[^ ]* //')
하지만 이렇게 하면 얼마나 더 빨라질까요?
md5sum=${line%%" "*}
filename=${line#*" "}
답변1
예, bash 내부 명령을 사용하면 많은 시스템 호출을 피할 수 있습니다. 특히 재귀가 있는 경우에는 더욱 그렇습니다.
또 다른 예: $(ls)에 대해 *를 사용해야 합니다.
Bash는 문자열에 대한 간단한 작업(잘라내기 및 바꾸기)을 수행하기 위한 몇 가지 방법을 제공합니다. 하지만 그게 다야. 왜냐하면 그것은 그것을 위해 설계되지 않았기 때문입니다. 예: 외부 명령 없이 문자열에 패턴이 있는지 확인하는 것은 어렵습니다.
외부 프로그램이 해당 작업에 더 잘 최적화되었습니다(cat, sed, grep, awk, cut, sort...).
답변2
변수 중 하나를 설정하여 테스트했습니다. 이 스크립트를 두 번 실행합니다.
while read line; do
md5sum=${line%%" "*}
#md5sum=$(echo $line | awk '{print $1}')
echo "SUM: $md5sum FILE:_$file"
done < manifest.Stuph.180620
먼저
md5sum=${line%%" "*}
다음은
md5sum=$(echo $line | awk '{print $1}')
"manifest.Stuph.180620" 파일의 길이는 100939줄(==약 14MiB)이며, 결과는 다음과 같습니다.
첫 번째 실행(bash의 내장 문자열 조작 사용)
real 0m4.750s
user 0m4.174s
sys 0m0.550s
두 번째 실행(파이프 사용)
real 10m54.255s
user 4m42.257s
sys 7m32.880s
나 같은 일부 사람들은 속도가 중요하다면 어쨌든 셸에서 장난을 치면 안 된다고 말할 것입니다. 그러나 때로는 작업을 완료하기 위해 어떤 환경을 사용하든 관계없이 더 효율적이기를 원할 수도 있습니다.
이렇게 하면 다음 사항에 유의하세요.
while read md5sum filename; do
(...etc...)
변수 할당을 수행하는 것보다 훨씬 효율적이지만 명령 대체/파이핑/awk 구성을 제거하는 지점은 아닙니다. 제가 가장 흥미로운 점은 bash 내장 성능과 외부 명령 사용의 차이입니다. 아름다운 내장 기능을 더욱 열심히 배우고 활용하겠습니다!