487바이트의 고정 길이 파일이 있고 각 레코드 위치 407-415(9바이트)는 숫자 필드입니다. 때로는 필드에 영숫자 조합이 표시되는 경우도 있습니다(123ABC123, ABC000123....). 레코드에 이와 같은 내용이 포함되어 있으면 해당 바이트에서 00000000을 바꾸고 싶습니다.
답변1
그리고 awk 솔루션
awk 'BEGIN{FS=OFS=""}{f=0;for(i=407;i<=415;i++){if($i!~/0-9/){f=1}};if(f){for(i=407;i<=415;i++){$i=0}};print }' fixed
필드 구분 기호를 비어 있도록 정의하고 각 문자는 필드입니다. 그런 다음 각 레코드의 플래그를 f
0(숫자로 가정)으로 설정합니다 . 문자 407-415를 /0-9/와 비교합니다. 불일치가 있으면 f를 1로 설정합니다. 그런 다음 f=1이면 9개 문자를 모두 0으로 바꾸고 해당 줄을 인쇄합니다.
답변2
다른 답변은 복잡해 보이기 때문에 여기에 간단한 sed
설명이 있습니다.
sed -E '/^.{406}[0-9]{9}/!s/(.{406}).{9}/\1000000000/'
확장된(options -E
) 정규식은 406개의 임의 문자( )로 시작하고 그 뒤에 9개의 숫자가 ^.{406}[0-9]{9}
오는 행(레코드가 행이라고 가정하고 그렇지 않으면 -z
GNU에 옵션을 추가함)과 일치 sed
하므로 407에서 415까지는 모두 숫자입니다. 역일치( )인 경우 처음 406자는 유지되고(대체의 첫 번째 부분을 나타냄) 다음 9자는 0으로 대체됩니다.^
.{406}
!
\1
()
텍스트 처리를 요청하는 경우 이는 바이트 처리가 아닌 텍스트 처리라는 점에 유의하세요. 멀티바이트 문자는 2바이트가 아닌 1문자로 계산됩니다.
답변3
이는 입력 파일이 텍스트인지 바이너리인지에 관계없이 작동합니다.
printf %s "$(head -c 406 test_file | xxd -p)" "000000000000000000" "$(tail -c $((487-415)) test_file | xxd -p)" | tr -d '\n' | fold -32 | xxd -p -r -c 16 > test_file_final
아니면 이거:
printf %s "$(head -c 406 test_file | xxd -p)" "$(head -c 9 /dev/zero | xxd -p)" "$(tail -c $((487-415)) test_file | xxd -p)" | tr -d '\n' | fold -32 | xxd -p -r -c 16 > test_file_final
다음을 사용할 필요는 없습니다. $((487-415))
... 간단히 사용할 수 있습니다 72
. 숫자의 출처를 더 명확하게 하기 위해 이렇게 합니다.
당신이 하고 있는 일은 파일의 처음 406바이트를 가져온 다음 9개의 널 바이트를 가져오는 것입니다(이 9개의 널 바이트는 예를 들어 18개의 0이 있는 일반 문자열에서 생성될 수 있습니다).[첫 번째 옵션]또는 9개의 원시 바이트/dev/제로 [두 번째 옵션]) 그런 다음 파일의 바이트 416부터 끝까지 시작한 다음 이 트리 블록을 함께 연결하여 원하는 출력을 만듭니다.
또는 다음으로 교체하고 싶다면문자 0개(아니요널 바이트) 다음을 사용하세요.
printf %s "$(head -c 406 test_file | xxd -p)" "303030303030303030" "$(tail -c $((487-415)) test_file | xxd -p)" | tr -d '\n' | fold -32 | xxd -p -r -c 16 > test_file_final
그럼에도 불구하고 위 명령은 다음과 같이 대체됩니다. 조건은 테스트되지 않습니다. 이 바이트에서 16진수 문자를 테스트하려면 null 바이트 대신 이것을 사용하십시오.:
단일 라인 버전:
if ! [[ "$(tail -c $((487-406)) test_file | head -c 9)" =~ [[:xdigit:]]{9} ]]; then printf %s "$(head -c 406 test_file | xxd -p)" "000000000000000000" "$(tail -c $((487-415)) test_file | xxd -p)" | tr -d '\n' | fold -32 | xxd -p -r -c 16 > test_file_final; fi
스크립트 버전:
if ! [[ "$(tail -c $((487-406)) "$1" | head -c 9)" =~ [[:xdigit:]]{9} ]]
then
printf %s "$(head -c 406 "$1" | xxd -p)" \
"000000000000000000" \
"$(tail -c $((487-415)) test_file | xxd -p)" \
| tr -d '\n' \
| fold -32 \
| xxd -p -r -c 16 \
> "${1}_with_replacement_done"
fi
또는 0개의 문자로 바꾸세요.:
단일 라인 버전:
if ! [[ "$(tail -c $((487-406)) test_file | head -c 9)" =~ [[:xdigit:]]{9} ]]; then printf %s "$(head -c 406 test_file | xxd -p)" "303030303030303030" "$(tail -c $((487-415)) test_file | xxd -p)" | tr -d '\n' | fold -32 | xxd -p -r -c 16 > test_file_final; fi
스크립트 버전:
if ! [[ "$(tail -c $((487-406)) "$1" | head -c 9)" =~ [[:xdigit:]]{9} ]]
then
printf %s "$(head -c 406 "$1" | xxd -p)" \
"303030303030303030" \
"$(tail -c $((487-415)) test_file | xxd -p)" \
| tr -d '\n' \
| fold -32 \
| xxd -p -r -c 16 \
> "${1}_with_replacement_done"
fi