以下是我的意见:
<array>
<string>extra1</string>
<string>extra2</string>
<string>Yellow
5</string>
注意:&#34;黄色&#34;之间有空格和换行符。和&#34; 5&#34;
我正在把它传给sed:
| sed -n 's#.*<string>\(.*\)</string>#\1#p'
我得到了输出:
extra1
extra2
我知道,因为sed从每个输入行的末尾剥离换行符,换行符不匹配 - 因此会占用结果。我已经阅读了有关从缓冲区添加下一行的文章,但我无法解决模式匹配中需要使用的内容,以使其工作。
我想要的输出是:
extra1
extra2
Yellow 5
(如果它有所作为,我正在使用Mac,所以我需要这个 - 我认为 - sed的FreeBSD变体。)
当然,如果另一种工具对我想达到的目标更好,我愿意接受建议!谢谢!
答案 0 :(得分:2)
关闭你的数组标签并尝试使用xmlstarlet和GNU sed:
xmlstarlet sel -t -v "//array/string" input.xml | sed '/ $/{:a;N;s/\n//;ta}'
输出:
extra1 extra2 Yellow 5
答案 1 :(得分:2)
加入线条将它们分开:
tr -d "\n" < file| grep -o "<string>[^<]*</string>"|sed 's/<string>\(.*\)<\/string>/\1/'
答案 2 :(得分:1)
perl
在OSX上可用,因此您可以使用:
perl -0ne 's#<string>([^<]*)</string>#sub{$x=$1;$x=~tr/\n/ /;print $x."\n";}->()#eg' file.xml
extra1
extra2
Yellow 5
或者,您可以使用gnu-awk
安装home brew
并使用:
awk -v RS= -v FPAT='<string>([^<]*)</string>' 'for(i=1; i<=NF; i++) {
gsub(/<\/?string>/, "", $i); gsub(/\n/, " ", $i); print $i}}' file.xml
extra1
extra2
Yellow 5
答案 3 :(得分:1)
任何时候你开始谈论&#34;缓冲&#34;或者&#34;持有空间&#34;或者除了s,g和p之外的其他结构(使用-n)你只是使用了错误的工具。所有关于sed的东西在20世纪70年代中期发明时已经过时了,当时发明了awk,所以只需使用awk。这是GNU awk用于多字符RS的一种方式:
$ awk -v RS='</?string>' '!(NR%2){gsub(/\n/," "); print}' file
extra1
extra2
Yellow 5
上述内容只是在将任何换行符转换为空白字符后打印<string>
和</string>
之间的任何内容。
对于其他问题,一种方法是:
$ cat tst.awk
{ rec = (rec=="" ? "" : rec " ") $0 }
END {
split(rec,f,"</?string>")
for (i=2;i in f;i+=2) {
print f[i]
}
}
$ awk -f tst.awk file
extra1
extra2
Yellow 5
答案 4 :(得分:0)
您可以使用xmllint
来解决此问题。我稍微修改了你的例子,以便你可以看到发生了什么。
<强>的test.xml 强>
<array>
<string1>extra1</string1>
<string2>extra2</string2>
<string3>Yellow
5</string3>
</array>
由于您希望字符串包含换行符,因此我将此值设为唯一。现在使用xmllint
和sed
来获取结果
[saxdaddy ~]$ x="$(xmllint --xpath "/array/string3" test.xml | sed '/^\/ >/d' | sed 's/<[^>]*.//g')"
[saxdaddy ~]$ echo $x
Yellow 5
xmllint的xpath
功能将以字典方式搜索XML。然后sed
将删除开头和结尾标记。对此的“技巧”是使用引号捕获变量,然后使用引号不来回显结果。
如果您的目标代码在文件路径中不是唯一的,那么您可以制作for
循环来查找$'\n'
(换行符)并将其设置为您的变量。
答案 5 :(得分:0)
请使用xidel之类的旨在解析xml的工具:
template <typename ...Ts>
static void log(Ts&&... ts)
{
(do_log(ts), ...);
std::cout << "\n";
}
// private:
template <typename T>
static void do_log(const T& arg) {
std::cout << arg;
}
template <typename T>
static void do_log(const std::vector<T>& v)
{
std::cout << '{';
const char* sep = "";
for (const auto& e : v) {
std::cout << sep;
do_log(e);
sep = ", ";
}
std::cout << '}';
}
template <typename T>
static bool try_log_any(const std::any& arg) {
if (auto* p = std::any_cast<T>(&arg)) {
do_log(*p);
return true;
}
return false;
}
template <typename... Ts>
static bool try_log_any_from(const std::any& arg) {
if ((try_log_any<Ts>(arg) || ...)) {
return true;
}
std::cout << "unsupported any type" << std::endl;
return false;
}
static void do_log(const std::any& arg) {
try_log_any_from<std::string, int, unsigned, char, float, double /*..*/>(arg);
}