인쇄할 수 없는 문자가 포함된 변수를 인쇄하는 방법은 무엇입니까?

인쇄할 수 없는 문자가 포함된 변수를 인쇄하는 방법은 무엇입니까?

$IFS인쇄할 수 없는 문자(예: 개행 문자)가 포함될 수 있는 변수의 값을 표시하고 싶습니다 .

이 작업을 수행하려면 다음 명령을 사용합니다.

echo -n "$IFS" | hexdump -C

이것은 나에게 잘 작동합니다.

그런데 이 명령을 사용하는데 문제가 있나요? 예를 들어 echo인쇄할 수 없는 문자를 인쇄하기 전에 다른 문자로 바꾸나요? stdout아니면 이와 유사한 문제가 있나요?

답변1

문자열을 시각적으로 표현하는 몇 가지 다른 방법:

POSIX

$ printf %s "$IFS" | od -vtc -to1
0000000      \t  \n  \0
        040 011 012 000
0000004
$ printf '%s\n' "$IFS" | LC_ALL=C sed -n l
 \t$
\000$

(추가 콘텐츠가 \n필요합니다. 그렇지 않으면 sed마지막 줄이 개행 문자로 끝나지 않으면 동작이 지정되지 않습니다.) POSIX에는 내 zsh처럼 NUL이 없습니다 sh. 입력에 NUL이 포함되어 있으면 동작이 지정되지 않습니다.$IFSsed

쉘 내장 함수

  • typeset -p(ksh, zsh, bash, yash)는 특정 문자열에 대한 명시적 출력을 제공할 수 있습니다.

    $ ksh93 -c 'typeset -p IFS'
    IFS=$' \t\n'
    $ zsh -c 'typeset -p IFS'
    typeset IFS=$' \t\n\C-@'
    $ mksh -c 'typeset -p IFS'
    typeset IFS=$' \t\n'
    $ a=$'\u00e9e\u301\u200b' ksh -c 'typeset -p a'
    typeset -x a=$'\u[e9]e\u[301]\u[200b]'
    

    그러나 후자(예각 악센트와 너비가 0인 공백 문자를 결합하기 위해 유니코드를 사용하는 경우)의 경우 zsh/mksh는 도움이 되지 않습니다( 에도 불구하고 LC_ALL=C typeset -p a) mksh -o utf8-mode. bash터미널로 전송될 때 출력은 일반적으로 명확하지 않습니다.

  • printf %qprintfGNU printf의 내장 기능을 사용 ksh93하고 다음을 수행하십시오 zsh.bash

    $ a=$'\u00e9e\u301\u200b' bash -c 'printf "%q\n" "$IFS" "$a" ""'
    $' \t\n'
    éé​
    ''
    $ a=$'\u00e9e\u301\u200b' ksh -c 'printf "%q\n" "$IFS" "$a" ""'
    $' \t\n'
    $'\u[e9]e\u[301]\u[200b]'
    ''
    \ $'\t'$'\n'$'\0'
    éé​
    ''
    $ a=$'\u00e9e\u301\u200b' sh -c '/usr/bin/printf "%q\n" "$IFS" "$a" ""'
    ' '$'\t\n'
    éé​
    ''
    $ a=$'\u00e9e\u301\u200b' zsh -c 'LC_ALL=C printf "%q\n" "$IFS" "$a" ""'
    \ $'\t'$'\n'$'\0'
    $'\303'$'\251'e$'\314'$'\201'$'\342'$'\200'$'\213'
    ''
    $ a=$'\u00e9e\u301\u200b' bash -c 'LC_ALL=C printf "%q\n" "$IFS" "$a" ""'
    $' \t\n'
    $'\303\251e\314\201\342\200\213'
    ''
    
  • q, qq, 의 매개변수 확장 플래그 qqq.qqqqzsh

    다양한 유형의 참조에 대해서는 qqqq다음과 같습니다 $'...'.

    $ a=$'\u00e9e\u301\u200b' zsh -c 'print -r -- ${(qqqq)a}'
    $'éé​'
    $ a=$'\u00e9e\u301\u200b' zsh -c '(){local LC_ALL=C; print -r -- ${(qqqq)a}}'
    $'\303\251e\314\201\342\200\213'
    

    다음 에 대한 참조만 사용합니다 q.q+필요그렇습니다(유니코드에 대한 경고는 여전히 존재하지만).

다양한 비표준 명령:

  • hex-dumper: hexdump, hd, xxd... 공급하려는 출력 printf %s "$var"(또는 print -rn -- "$var"ksh/zsh를 사용하거나 ... echo -nE - "$var"을 사용 zsh).

  • cat -vte또는cat -A

  • uconv -x hex문자의 유니코드 코드 포인트(인코딩된 바이트의 16진수 값이 아님)의 경우 UTF-8에서만 작동합니다(입력은 전처리될 수 있지만 iconv -t utf-8로케일 인코딩에서 유효한 텍스트인 경우에만 해당).

  • uconv -x name역할 이름의 경우

  • recode ..dump. 16진수 및 이름이지만 더 적은 수의 유니코드 문자를 이해합니다(최신 버전의 유니코드로 업데이트되지 않음). 그러나 UTF-8이 아닌 로케일에서는 작동합니다.

답변2

특히 의 경우 IFS반드시 인용하고 싶거나 그렇지 않으면 쓸모가 없게 됩니다. 이미 그렇게 했으니 문제 없습니다.

의 경우는 echo경우에 따라 다릅니다. 일부 버전은 echo기본적으로 백슬래시 이스케이프를 처리하지만 일부는 그렇지 않습니다. Bash는 그렇지 않지만 zsh는 다음을 수행합니다.

$ bash -c 'echo "foo\nbar"'
foo\nbar
$ zsh -c 'echo "foo\nbar"'
foo
bar

사용하는 것이 더 좋습니다 printf: printf "%s" "$IFS" | hexdump -C.

또한보십시오:왜 printf가 echo보다 나은가요?

printf "%q" "$IFS"Bash 및 zsh에서도 작동합니다.

\0이는 Bash가 NUL 바이트( )를 전혀 처리할 수 없는 반면 zsh는 처리할 수 있다는 점을 제외하면 좋은 상태를 유지해야 합니다 . 큰 타격:

$ var=$'foo\0bar'
$ printf "%q\n" "$var"
foo

지쉬어:

$ var=$'foo\0bar'
$ printf "%q\n" "$var"
foo$'\0'bar

답변3

Bash에서 작동하지 않는 유일한 문자는 null입니다.

$ var="$(perl -wE 'print map chr, 0 .. 255')"
$ echo -n "$var" | xxd
0000000: 0102 0304 0506 0708 090a 0b0c 0d0e 0f10  ................
0000010: 1112 1314 1516 1718 191a 1b1c 1d1e 1f20  ............... 
0000020: 2122 2324 2526 2728 292a 2b2c 2d2e 2f30  !"#$%&'()*+,-./0
0000030: 3132 3334 3536 3738 393a 3b3c 3d3e 3f40  123456789:;<=>?@
0000040: 4142 4344 4546 4748 494a 4b4c 4d4e 4f50  ABCDEFGHIJKLMNOP
0000050: 5152 5354 5556 5758 595a 5b5c 5d5e 5f60  QRSTUVWXYZ[\]^_`
0000060: 6162 6364 6566 6768 696a 6b6c 6d6e 6f70  abcdefghijklmnop
0000070: 7172 7374 7576 7778 797a 7b7c 7d7e 7f80  qrstuvwxyz{|}~..
0000080: 8182 8384 8586 8788 898a 8b8c 8d8e 8f90  ................
0000090: 9192 9394 9596 9798 999a 9b9c 9d9e 9fa0  ................
00000a0: a1a2 a3a4 a5a6 a7a8 a9aa abac adae afb0  ................
00000b0: b1b2 b3b4 b5b6 b7b8 b9ba bbbc bdbe bfc0  ................
00000c0: c1c2 c3c4 c5c6 c7c8 c9ca cbcc cdce cfd0  ................
00000d0: d1d2 d3d4 d5d6 d7d8 d9da dbdc ddde dfe0  ................
00000e0: e1e2 e3e4 e5e6 e7e8 e9ea ebec edee eff0  ................
00000f0: f1f2 f3f4 f5f6 f7f8 f9fa fbfc fdfe ff    ...............

printf이식성이 더 뛰어나지 echo만 내 시스템과 쉘(bash)에서는 출력이 정확히 동일합니다.

printf %s "$var"

답변4

나는 QBash의 매개변수 변환 연산자를 좋아합니다:

echo "${IFS@Q}"

산출:

$' \t\n'

$'string'참조는ANSI-C 인용문.

Q연산자는 SSH를 통해 명령에 인수를 전달하는 데에도 사용할 수 있습니다.

f='filename with space'
ssh "$host" "ls -l ${f@Q}"

이것매개변수 확장섹션에는 모든 연산자 목록이 포함되어 있습니다. 이 A연산자도 유용합니다:

a=(array with 'various elements')
echo "${a[@]@A}"

산출:

declare -a a=([0]="array" [1]="with" [2]="various elements")

관련 정보