$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이 포함되어 있으면 동작이 지정되지 않습니다.$IFS
sed
쉘 내장 함수
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 %q
printf
GNUprintf
의 내장 기능을 사용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
.qqqq
zsh
다양한 유형의 참조에 대해서는
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
나는 Q
Bash의 매개변수 변환 연산자를 좋아합니다:
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")