변수는 같은 값을 출력하지만 실제 값은 다릅니다

변수는 같은 값을 출력하지만 실제 값은 다릅니다

다음 구문을 사용하여 xml 파일에서 단어를 캡처합니다. 또한 xargs를 사용하여 공백을 제거합니다.

var=` find /tmp -name '*.xml' -exec sed -n 's/<Name>\([^<]*\)<\/Name>/\1/p' {} +  |  xargs `

echo $var
TOPIC

지금까지는 괜찮아 보이는데

하지만 printf는 다른 것을 보여줍니다

printf "%q\n" "$var"
$'TOPIC\r'

더 자세히 살펴보겠습니다.

[[ TOPIC == $var ]] && echo they are equal

"그들은 동일합니다"를 인쇄하지 않습니다

하지만 $var를 인쇄하면 다음과 같은 결과가 나옵니다.

echo $var
TOPIC

그래서 상황이 분명해진 후에

가장 큰 문제는 다음과 같습니다.

변수에서 추가 문자( $ , \r )를 제거하는 방법 -

$'TOPIC\r'

답변1

이는 이 변수의 내용을 나타내기 위해 구현에서 제공하는 시각적 표현입니다 $'TOPIC\r'. 이 표현을 제공하기 위해 printfksh93의 $'...'인용 형식(현재 다른 쉘에서도 지원됨 zsh) 을 사용합니다. bash이러한 셸에서는 동일한 내용으로 var=$'TOPIC\r'변수가 생성됩니다 . $var이 인용 형식에서는 \r캐리지 리턴 문자를 나타냅니다.

이것은 터미널로 전송될 때 커서를 줄의 시작 부분으로 이동시키는 문자입니다. 문자 모양이 연결된 일반 문자가 아닌 터미널의 제어 문자입니다.

printf 'ABC\rX\n'

( printf, 그 안에는체재매개변수는 \rCR(문자의 의미)로도 인식되며 다음과 같이 표시됩니다.

XBC

당신이 쓰는 경우 :

printf 'ABC\rX\n' | pv -qL3

속도를 늦추면 무슨 일이 일어나는지 볼 수 있습니다.

이를 제거하려면 ksh93과 유사한 셸(ksh93, zsh, bash 또는 mksh)을 사용하여 다음을 수행할 수 있습니다.

var=${var//$'\r'}

\r[:space:]캐릭터 로도 분류됩니다 . 따라서 다음을 사용하여 모든 공백 문자를 제거할 수도 있습니다.

var=${var//[[:space:]]}

CR 문자(변수 끝에 있는 문자)만 제거하려면 다음을 수행하십시오.

var=${var%$'\r'}

(더 많은 쉘에 이식 가능해야 합니다).

POSIXly(이식 가능한 스크립트에서와 마찬가지로 sh) 다음을 수행할 수 있습니다.

var=$(printf %s "$var" | tr -d '\r')

그러나 \n변수 내용의 끝에서 개행(또는 개행, 일명 LF)도 제거된다는 점에 유의하세요.

그런데 ism [[ TOPIC = $var ]] ( kshzsh 및 bash에서도 지원됨)은 동등성 테스트 연산자가 아닌 패턴 일치 연산자입니다(ksh/bash를 에뮬레이션하지 않는 경우 제외 ). 동등성 테스트를 수행 zsh해야 합니다 .[[ TOPIC = "$var" ]]var=*; [[ TOPIC = $var ]]진짜예를 들어 (그리고 var='[x]'; [[ $var = $var ]]반환됩니다잘못된).

또한 기억해주세요echo임의의 데이터를 출력하는 데 사용할 수 없습니다.그리고매개변수 확장은 일반적으로 인용되어야 합니다..

$ var=$'TOPIC\r'
$ printf '%s\n' "$var" # zsh (my shell) builtin
TOPIC
$ printf '%q\n' "$var"
TOPIC$'\r'
$ /usr/bin/printf '%q\n' "$var" # GNU printf
'TOPIC'$'\r'
$ (export var; bash -c 'printf "%q\n" "$var"') # bash builtin
$'TOPIC\r'
$ (export var; ksh93 -c 'printf "%q\n" "$var"') # ksh93 builtin
$'TOPIC\r'
$ (export var; dash -c 'printf "%q\n" "$var"')
dash: 1: printf: %q: invalid directive

%q표준 printf지시문은 아니며 모든 구현이 이를 지원하는 것은 아니며 동작은 구현마다 다릅니다. sed -n l문자열의 명확한 시각적 표현을 얻는 이식 가능/표준 방법입니다(출력은 구현마다 다르지만).

$ printf '%s\n' "$var" | sed -n l
TOPIC\r$

즉, $줄의 끝을 표시합니다(뒤에 공백이 있는 줄에 유용함).

$ var=${var//$'\r'}
$ printf '%s\n' "$var" | sed -n l
TOPIC$

답변2

is 기호는 \rC에서 상속되었으며 캐리지 리턴 문자를 나타냅니다. 파일에 DOS/Windows 스타일 CRLF 줄 끝이 있을 가능성이 높습니다. CR을 다른 문자로 처리 sed하면 xargs전달됩니다. 같은 줄에 있는 <Name>...</Name>태그 이외의 다른 것도 이 sed에 의해 전달됩니다.

$ echo 'foo <Name>bar</Name><Num>123</Num>' | sed 's/<Name>\([^<]*\)<\/Name>/\1/'
foo bar<Num>123</Num>

sed다음과 같이 XML 파일에서 필드를 선택하는 경우 줄 주위의 다른 내용도 제거 할 수 있습니다 .

$ echo 'foo <Name>bar</Name><Num>123</Num>' | sed 's/.*<Name>\([^<]*\)<\/Name>.*/\1/'
bar

또한 .*.

관련 정보