고정 길이 파일이 sed 또는 awk로 대체됨

고정 길이 파일이 sed 또는 awk로 대체됨

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

필드 구분 기호를 비어 있도록 정의하고 각 문자는 필드입니다. 그런 다음 각 레코드의 플래그를 f0(숫자로 가정)으로 설정합니다 . 문자 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}오는 행(레코드가 행이라고 가정하고 그렇지 않으면 -zGNU에 옵션을 추가함)과 일치 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

관련 정보