bash 명령 문자열의 완전 문자를 어떻게 확인할 수 있습니까?


15

오늘 아침 bash 터미널 에서이 이상한 행동을했습니다.

user@home:/home/user$ [ -f /etc/openvpn/client.conf ] && echo true
bash: [: missing «]»
user@home:/home/user$ [ -f /etc/openvpn/client.conf ] && echo true
true
  • 첫 번째 명령은 gedit로 편집 한 스크립트에서 붙여 넣었습니다 .
  • 두 번째는 터미널에 직접 입력 되었습니다.

약간의 파기 후에 30 번째 문자 (client.conf와 "]"사이의 공백) 를 제거하고 공백으로 바꾸면 명령이 다시 작동 한다는 것을 알았 습니다.

내 가정은 옳았다 : 알 수없는 빈 문자가 명령에 빠져 들었지만 질문은 다음과 같습니다.

  1. 터미널에서 해당 문자를 표시하여 명령을 디버깅 할 수 있습니까? 그리고 더 중요한 :
  2. 이 문제가 다시 발생하지 않도록하려면 어떻게해야합니까?

BTW, Ubuntu 18.04 / 프랑스어를 실행 중입니다. 명령을 붙여 넣은 스크립트는 USB 드라이브에 있으며 Windows에서도 편집되었을 수 있습니다.


좋은 답변 감사합니다. 잘못된 문자는 c2 a0 비 공백 공간 UTF-8 문자입니다. 질문 나오지도 함께 특별한 'M-BM-'문자를 제거하는 방법은 그 문자에 대한 흥미로운 사실이있다.

이상한 점은 스크립트에이 문자가 없다는 것입니다. 그래서 나는 그것이 어디에서 왔는지 모른다.


3
이러한 문자를 강조 표시하는 편집기를 사용하십시오. 구문 강조도 많은 도움이됩니다. 웹에서 터미널로 직접 붙여 넣지 말고 항상 위에서 언급 한 편집기를 사용하십시오.
choroba

2
히스토리 목록에서 문제 명령을 찾은 다음 16 진 디스플레이 프로그램을 통해 출력을 파이프하십시오. 긴 목록을 넘어갈 필요가 없도록하려면 명령을 다시 실행하여 기록 목록의 맨 아래에 놓고 명령을 실행하십시오 history 2|xxd( history명령 자체가 항상 목록의 마지막 이므로 ) history|grep "CommandWithProblem"|xxd. 대신 다른 16 진수 디스플레이 프로그램을 사용할 수 xxd있지만 기본값은 내가 좋아하는 형식입니다.
AFH

@Gabriel Glenn, 답변이 도움이 된 각각에 대해 의견을 제시하지 말고 틱을 사용하여 최상의 / 가장 유용한 / 모든 답변을 " 허용 " 으로 표시하십시오 . 정보
Attie

1
@Attie, 그렇습니다. 저는 보통 24 시간 동안 최선의 답변을 받아들입니다. meta.stackexchange.com/questions/5234/…
Gabriel Glenn

1
개인적으로 사용 set -x합니다. 명령과 분할 방법이 표시됩니다. 반드시 "나쁜 캐릭터는 여기에"라고 말할 필요는 없지만 배쉬가 해당 캐릭터에 분할되지 않았 음을 보여줍니다.
Patrick

답변:


11

한 가지 옵션은 16 진 뷰어 또는 편집기에서 사용하려는 문자를 보는 것입니다. hexdump터미널로 제한되어 있다면 좋은 옵션입니다.

$ hexdump -Cv <<"EOF"
> [ -f /etc/openvpn/client.conf ] && echo true
> EOF
00000000  5b 20 2d 66 20 2f 65 74  63 2f 6f 70 65 6e 76 70  |[ -f /etc/openvp|
00000010  6e 2f 63 6c 69 65 6e 74  2e 63 6f 6e 66 20 5d 20  |n/client.conf ] |
00000020  26 26 20 65 63 68 6f 20  74 72 75 65 0a           |&& echo true.|
0000002d

당신은이 것을 여기에서 볼 수 있습니다 space, close-square-brace, space올 - 0x20, 0x5D, 0x20.

이 값은 16 진수로 표시되는 ASCII 코드 입니다. 범위를 벗어난 값은 0x20- 0x7E아니다 " 인쇄 가능한 문자 " ASCII에 관한 한, 가장 가능성이 명령 줄 인터페이스와 잘 재생되지 않습니다까지한다.

참고 : 위 의 예제 에서 사용하기 위해 첫 번째 " 파손 된 "행을 복사 hexdump했으므로 ASCII아닌 공백 을 원본과 렌더링 된 질문 사이의 ASCII 공백으로 바꿨습니다.


이를 반복하려면 다음 단계를 수행하십시오.

  1. 입력 hexdump -Cv <<"EOF"하고 누르십시오Enter
  2. 사용하려는 텍스트를 붙여 넣습니다
  3. EOF자체 줄에 입력 하고Enter

터미널과 명령 행 인터페이스는 발견 한 것처럼 특수 문자를 잘 처리하지 못합니다. 문서 서식에 매우주의하지 않으면 " 스마트 따옴표 "를 사용하여 Microsoft Word (및 기타)에 문제가있을 수 있습니다 .

차이를 스팟 : (상단이 " 둥근 따옴표 ", 하단은 " 곧은 따옴표 ")

스마트 따옴표와 직선 따옴표의 예

$ hexdump -Cv <<"EOF"
> quoted string
> EOF
00000000  e2 80 9c 71 75 6f 74 65  64 20 73 74 72 69 6e 67  |...quoted string|
00000010  e2 80 9d 0a                                       |....|
00000014

여기서, 오픈 따옴표는 간단한 ASCII 따옴표 (하지 ")하지만, 유니 코드 /이다 UTF-8 시리즈 - 0xE2, 0x80, 0x9C, 또는 U+201C- 예상대로 터미널이 처리 할 것이다.

Kiwy의 제안 cat -A도 그 일을한다 :

$ cat -A <<"EOF"
> quoted string
> EOF
M-bM-^@M-^\quoted stringM-bM-^@M-^]$

참고 :을 사용할 때echo "..." | hdbash가 검사하려는 문자열의 일부를 대체 할 가능성이 있습니다. 이것은 스크립트의 구성 요소를 검사 할 때 특히 중요합니다.

예를 들어보십시오 :

$ echo "${USER}"
attie

$ echo "`whoami`"
attie

$ echo "$(whoami)"
attie

$ cat <<EOF
> ${USER}
> EOF
attie

이 방법들은 컴포넌트를 관련 텍스트로 대체합니다. 이를 피하려면 다음 방법 중 하나를 사용하십시오. 작은 따옴표 ( ')와 " quoted heredoc " ( "EOF")을 사용하십시오.

$ echo '${USER}'
${USER}

$ echo '`whoami`'
`whoami`

$ echo '$(whoami)'
$(whoami)

$ cat <<"EOF"
> ${USER}
> EOF
${USER}

이 솔루션은 작동합니다 : echo "[ -f /etc/openvpn.ovpn ]" | hd 리턴 [...] c2 a0 [...]. 우리는 c2 a0 UT-8 문자 비 공백 공간을 볼 수 있습니다
Gabriel Glenn

18

cat다음 -A옵션 과 함께 사용할 수 있습니다 : 매뉴얼에서 :

   -A, --show-all
          equivalent to -vET
   -E, --show-ends
          display $ at end of each line
   -T, --show-tabs
          display TAB characters as ^I
   -v, --show-nonprinting
          use ^ and M- notation, except for LFD and TAB

그래서 cat -A yourscrip.sh당신에게 보이지 않는 이상한 문자가 표시됩니다.


7
이 솔루션은 작동합니다 : echo "[ -f /etc/openvpn.ovpn ]" | cat -A리턴 [ -f /etc/openvpn/client.ovpnM-BM- ]$. 우리는 M-BM- UT-8 문자 비 공백 공간을 볼 수 있습니다
Gabriel Glenn

@GabrielGlenn 이것이 당신에게 도움이 된 것을 기쁘게 생각합니다.
Kiwy

9

echo "<your command>" | hd작동해야합니다. 백 스페이스 (0x08) 또는 코드가 80보다 큰 문자를 찾으십시오. echo "<your command>" | wc -b카운트가보고있는 것과 일치하는지 확인하는 것도 좋습니다.

이름이 "Office"인 파일에서 생성 된 파일에서 물건을 복사하는 것은 위험합니다. 이러한 소프트웨어는 종종 문자를 대체 할 자유가 필요하기 때문입니다. 프랑스어에서는 큰 따옴표는 "guillemets"로 대체하고 영어는 "일반"으로 대체합니다. 열기 / 닫기 등가물. 내가 찾은 가장 어려운 것은 파일 이름 중간에 0 너비의 비 끊김 공간 (3 일 동안의 서버 다운 타임 ...)이었습니다.


2
그것의 가치에 대한 언급은 hd대한 짧은 hexdump또한 Attie의 대답에 언급된다.
Mikael Kjær

@ MikaelKjær-우분투에서 hd와 동일합니다 hexdump -C.
AFH

1
@ xenoid : Office Writer로 편집하지 않고 'Windows에서 편집했습니다.'라고 말했지만 우리는 미친 것이 아닙니다. 편집 된 경우 메모장 ++로 된 것입니다.
가브리엘 글렌

1
이 솔루션은 작동합니다 : echo "[ -f /etc/openvpn.ovpn ]" | hd 리턴 [...] c2 a0 [...]. 우리는 볼 수 있습니다 C2의 A0 UT-8 문자 줄 바꿈하지 않는 공간
가브리엘 글렌

2

Bash 및 zsh와 같은 다른 쉘은 편집기에서 현재 명령 행을 열 수 있습니다. 배쉬의 기본 바로 가기는 C-x C-e( CtrlX CtrlE), 그리고 최초의 가능한 열립니다 $VISUAL, $EDITOR그리고 이맥스. 실제로 이것은 복잡한 명령을 디버깅하고 수정하는 데 매우 중요합니다. 어떻게 보느냐에 따라 zsh는 여기에서 bash보다 더 친숙합니다. 편집기가 종료되면 bash는 즉시 명령을 실행하지만 zsh는 사용자가 누르기를 기다립니다 Enter(명령을 편집 할 수있는 더 많은 기회 제공).

편집기에서 명령을 연 후 비 ASCII 문자를 다르게 표시하도록 편집기를 구성 할 수 있습니다.

예를 들어, Vim 에서는 다음 설정을 사용하십시오.

set encoding=latin1
set isprint=
set display+=uhex

여기에 이미지 설명을 입력하십시오

또는 다른 답변의 방법을 조정하십시오.

bash-4.4$ f() { cat -A "$@"; false; }   # exit false to prevent bash from running the command
bash-4.4$ VISUAL=f
bash-4.4$ [ -f /etc/openvpn/client.conf ] && echo true  # C-x C-e here
[ -f /etc/openvpn/client.confM-BM- ] && echo true$
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.