문자를 읽은 다음 고정 길이 문자열(파일에서 null로 끝나지 않고 앞의 문자로 길이가 지정됨)을 읽고 싶습니다.
Bash 스크립트에서 이 작업을 어떻게 수행할 수 있나요? 후처리를 수행할 수 있도록 문자열 변수를 어떻게 정의합니까?
답변1
쉘 유틸리티를 계속 사용하려면 head
여러 바이트를 추출하고 od
바이트를 숫자로 변환하는 데 사용할 수 있습니다.
export LC_ALL=C # make sure we aren't in a multibyte locale
n=$(head -c 1 | od -An -t u1)
string=$(head -c $n)
그러나 이작동하지 않습니다바이너리 데이터의 경우. 두 가지 질문이 있습니다:
명령 대체
$(…)
바마지막 개행 문자명령 출력에서. 매우 간단한 해결 방법이 있습니다. 출력이 개행 문자가 아닌 문자로 끝나는지 확인한 다음 해당 문자를 제거하십시오.string=$(head -c $n; echo .); string=${string%.}
대부분의 쉘과 마찬가지로 Bash는 처리에 능숙하지 않습니다.널 바이트. Bash 4.1부터 명령 대체 결과에서 널 바이트가 간단히 제거됩니다. Dash 0.5.5와 pdksh 5.2는 동일한 동작을 가지며 ATT ksh는 첫 번째 null 바이트에서 읽기를 중지합니다. 일반적으로 셸과 해당 유틸리티는 바이너리 파일을 처리하는 데 적합하지 않습니다. (널 바이트를 지원하도록 설계된 Zsh는 예외입니다.)
바이너리 데이터가 있는 경우 Perl 또는 Python과 같은 언어로 전환해야 합니다.
<input_file perl -e '
read STDIN, $c, 1 or die $!; # read length byte
$n = read STDIN, $s, ord($c); # read data
die $! if !defined $n;
die "Input file too short" if ($n != ord($c));
# Process $s here
'
<input_file python -c '
import sys
n = ord(sys.stdin.read(1)) # read length byte
s = sys.stdin.read(n) # read data
if len(s) < n: raise ValueError("input file too short")
# Process s here
'
답변2
쉘에서 바이너리를 처리하고 싶다면 가장 좋은 옵션은 (유일한?) 다음을 사용하는 것입니다.16진수 덤프도구.
hexdump -v -e '/1 "%u\n"' binary.file | while read c; do
echo $c
done
X바이트만 읽기:
head -cX binary.file | hexdump -v -e '/1 "%u\n"' | while read c; do
echo $c
done
길이를 읽은 다음(길이로 0을 사용) 바이트 십진수 값으로 "문자열"을 읽습니다.
len=$(head -c1 binary.file | hexdump -v -e '/1 "%u\n"')
if [ $len -gt 0 ]; then
tail -c+2 binary.file | head -c$len | hexdump -v -e '/1 "%u\n"' | while read c; do
echo $c
done
fi
답변3
exec 3<binary.file # open the file for reading on file descriptor 3
IFS= #
read -N1 -u3 char # read 1 character into variable "char"
# to obtain the ordinal value of the char "char"
num=$(printf %s "$char" | od -An -vtu1 | sed 's/^[[:space:]]*//')
read -N$num -u3 str # read "num" chars
exec 3<&- # close fd 3
답변4
이것은 바이너리 파일을 복사합니다.
while read -n 1 byte ; do printf "%b" "$byte" ; done < "$input" > "$output"