Linux

變數列印了相同的值,但實際上值是 diff

  • January 17, 2018

用於擷取 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'

$'TOPIC\r'是您的printf實現給出的視覺表示,用於表示該變數的內容。它使用 ksh93 的$'...'引用形式(現在也受zsh,bash和其他一些 shell 支持)為您提供該表示。在這些 shell 中,var=$'TOPIC\r'將創建一個$var具有相同內容的變數。在那種形式的引用中,\r代表一個輸入符。

這是一個字元,當發送到終端時會使終端將游標移動到行首。它是終端的控製字元,它不是帶有與之關聯的字形的普通字元。

printf 'ABC\rX\n'

( printf, 在其格式參數中也辨識\r為 CR 字元的含義) 顯示為:

XBC

如果你寫:

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

慢下來,你可以看看會發生什麼。

要刪除它,使用類似 ksh93 的 shell(ksh93、zsh、bash 或 mksh),您可以這樣做

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

\r也被歸類為[:space:]字元。因此,您還可以使用以下方法刪除所有空格字元:

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

要僅刪除該 CR 字元(變數末尾的字元):

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

(應該可以移植到更多的shell)。

POSIXly(如在可移植sh腳本中),您可以執行以下操作:

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

儘管請注意,它還會\n從變數內容的末尾刪除換行符(又名換行符又名 LF aka )。

附帶說明一下,[[ TOPIC = $var ]] (zsh 和 bash 也支持一個kshism)是一個模式匹配運算符,而不是一個相等性測試運算符(除了zsh不模擬 ksh/bash 時),您需要[[ TOPIC = "$var" ]]測試相等性,例如var=*; [[ TOPIC = $var ]]會返回true(並且var='[x]'; [[ $var = $var ]]會返回false)。

還要記住,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$

引用自:https://unix.stackexchange.com/questions/417756