変数は同じ値を出力しますが、実際の値は異なります

変数は同じ値を出力しますが、実際の値は異なります

次の構文を使用して、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$

おすすめ記事