Unix tr 查找和替换

16

这是我在从网站上 wget 下载标准网页时使用的命令。

tr '<' '\n<' < index.html

然而它给了我新的一行,但没有再次添加左括号。

 echo "<hello><world>" | tr '<' '\n<'

返回

 (blank line which is fine)
 hello>
 world>
代替
 (blank line or not)
 <hello>
 <world>

发生了什么问题?

4个回答

33

这是因为tr只进行逐字符的替换(或删除)。

尝试使用sed代替。

echo '<hello><world>' | sed -e 's/</\n&/g'

或者 awk

echo '<hello><world>' | awk '{gsub(/</,"\n<",$0)}1'

或者perl

echo '<hello><world>' | perl -pe 's/</\n</g'

或者ruby

echo '<hello><world>' | ruby -pe '$_.gsub!(/</,"\n<")'

或者 python

echo '<hello><world>' \
| python -c 'for l in __import__("fileinput").input():print l.replace("<","\n<")'

1
@ephemient SunOS(我校的afs系统) - Kamran224
在SunOS上,您必须手动输入新行。在替换字段中,按enter键并继续进行替换操作。对于tab,您必须手动敲击空格(8次),或者根据您的机器默认tab限制进行操作。 - jaypal singh
@ephemient 你没有给出 c++ 的实现!!:P +1 - jaypal singh
2
@Jaypal 一个由8个空格组成的字符串并不等同于制表符;你需要一个真正的制表符字符。这个8个空格的事情是关于制表位而非制表符的。 - Michael J. Barber
1
在未指定Unix机器上使用perl。在这些机器上使用sed或者tr可能会暴露它们不支持预期的功能。 - Yuri
显示剩余3条评论

3
如果您有GNU的grep,这可能适用于您:
grep -Po '<.*?>[^<]*' index.html

应该通过整个HTML,但每个标签应该从行的开头开始,并可能在同一行上跟随非标记文本。

如果您只想要标记:

grep -Po '<.*?>' index.html

然而,你需要知道,使用正则表达式解析HTML并不是一个好主意


3
放置换行符的顺序很重要。此外,您可以转义“<”。
`tr '<' '<\n' < index.html` 

同样有效。


2
这对你有用吗?
awk -F"><" -v OFS=">\n<" '{print $1,$2}'

[jaypal:~/Temp] echo "<hello><world>" | awk -F"><" -v OFS=">\n<" '{$1=$1}1';
<hello>
<world>

您可以在 awk{} 动作前面放置一个正则表达式 / /(您希望发生的行),以实现筛选。

1
如果一行中有多个 ><,则 '{$1=$1}1' 更短且有效。 - ephemient
这会比问题中替换更少的<字符。 - Michael J. Barber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接