sed를 사용하여 긴 숫자를 16진수로 변환

sed를 사용하여 긴 숫자를 16진수로 변환

sed3자리보다 긴 숫자를 16진수로 변환하는 명령을 만들려고 합니다 . 즉, 이와 같은 문자열은 현재 내가 가지고 있는 124 3275 7535124 0xccb 0x1d6f입니다.

sed 's@\([0-9]\{4,\}\)@sh -c "printf 0x%x \1"@ge'

그러나 문자열이 일치하지 않으면 변경되지 않은 문자열을 외부 명령으로 실행하려고 시도하므로 위의 예제 문자열에서는 다음과 같은 결과를 얻습니다.

sh: 1:124: 찾을 수 없음

내가 하고 싶은 일을 어떻게 달성할 수 있나요? (아직도 sed?

답변1

질문 제목에 따르면 "with sed"는 아니지만 sed에서 Perl로 전환하면 다음과 같은 동등한 표현을 사용할 수 있습니다.

perl -p -e 's/\b\d{4,}\b/sprintf "%#x", $&/ge'

이렇게 하면 체인의 다른 표현식을 어느 정도 보존할 수 있습니다.

답변2

명령 플래그의 GNU 구현은 e평가입니다.ssed패턴 공간의 내용대체를 (성공적으로) 적용하고 평가 대신 패턴 공간을 출력으로 대체한 후치환.

여기서는 다음 입력에 대해:

foo 1234 123

다음을 포함하는 패턴 공간을 생성하려면 대체가 필요합니다.

printf %s 'foo '
printf 0x%x 1234
printf %s ' 123'

쉘 명령을 통해 e이를 플래그로 변환하십시오 . foo 0x3d2 123불가능한 것은 아닙니다. 예를 들면 다음과 같습니다.

LC_ALL=C sed -E "
  /[0-9]{4}/!b # optimisation
  s/'/&\\\\&/g
  s/[0-9]{4,}/'\nprintf 0x%x &\nprintf %s '/g
  s/.*/printf %s '&'/e"

그러나 이는 다소 어색하며 일치하는 각 입력 행에 대해 쉘을 실행하는 것을 의미합니다. GNUism을 사용하지 않고도 다음을 수행할 수 있습니다.

LC_ALL=C sed "
  s/'/&\\\\&/g
  s/[0-9]\{4,\}/'\\
printf 0x%x &\\
printf %s '/g
  s/.*/printf %s '&\\
'/" | sh

어느 것이 실행될 것인가하나 sh.

또한 이와 같이 임의의 데이터를 쉘 코드로 평가하는 것은 나를 긴장시키는 경향이 있습니다. 예를 들어, 위의 LC_ALL=C가 없으면 임의의 명령 실행 취약점이 됩니다. 예를 들어 다음과 같은 출력을 시도해 보세요.

printf '0000\200; echo GOTCHA>&2\n'

UTF-8 로케일.

여기서는 다음과 같은 것을 사용하는 것이 좋습니다 perl.

perl -pe 's/\d{4,}/sprintf "0x%x", $&/ge'

perl로고는 e귀하의 기대에 더 부합합니다. 대체 항목을 코드로 평가합니다(그리고 perlGNU처럼 매번 새로운 Perl 인터프리터를 시작하지 않습니다).sede

답변3

awk그것은정확히이러한 유형의 광범위한 텍스트 조작입니다. 보조 도구에 파이프를 연결할 필요가 없습니다.

awk '{ for( fn=1;fn<=NF;fn++ ){
           fmat=(length($fn)>3)?"0x%x":"%s"
           dlim=(fn==NF?"\n":" ")  
           printf( fmat dlim, $fn )}}' <<<'124 3275 7535' 

귀하의 예를 바탕으로 출력 :

124 0xccb 0x1d6f

답변4

저는 Peter.O가 댓글에서 말한 내용에 동의합니다. 다음은 한 가지 방법입니다 ( 각 숫자 끝에 bash있어야 합니다 ).

echo '124 3275 7535 ' | while read -d ' ' x; do [ ${#x} -ge 4 ] && printf "0x%x " $x || printf "%d " $x; done

입력 스트림의 줄 끝에 (예제에서) 이 없는 경우 sed유용합니다 .

echo '124 3275 7535' | sed 's/$/ /' | while read -d ' ' x; do [ ${#x} -ge 4 ] && printf "0x%x " $x || printf "%d " $x; done

관련 정보