使用以下语法来捕获 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'
视觉表示。printf
它使用 ksh93 的$'...'
引用形式(现在也受 和一些其他 shell 支持zsh
)bash
来为您提供该表示形式。在这些 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 又名)。
顺便说一句,[[ TOPIC = $var ]]
(ksh
zsh 和 bash 也支持 ism)是一个模式匹配运算符,而不是相等测试运算符(除了zsh
不模拟 ksh/bash 时),您需要[[ 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符号\r
继承自 C,表示回车符。您的文件很可能具有 DOS/Windows 风格的 CRLF 行结尾。sed
并将xargs
CR 视为另一个字符,它就会被传递。尽管同一行上<Name>...</Name>
标记之外的任何其他内容也会被该 sed 传递。
$ echo 'foo <Name>bar</Name><Num>123</Num>' | sed 's/<Name>\([^<]*\)<\/Name>/\1/'
foo bar<Num>123</Num>
如果您从这样的 XML 文件中选择字段,您可能希望sed
同时删除该行周围的任何其他内容:
$ echo 'foo <Name>bar</Name><Num>123</Num>' | sed 's/.*<Name>\([^<]*\)<\/Name>.*/\1/'
bar
这也应该消除最后的任何 CR,因为它们与.*
.