【问题标题】:Linux Text File ManipulationLinux 文本文件操作
【发布时间】:2010-01-20 11:36:11
【问题描述】:

我有一个格式为:

<a href="http://www.wowhead.com/?search=Superior Mana Oil">  
<a href="http://www.wowhead.com/?search=Tabard of Brute Force">  
<a href="http://www.wowhead.com/?search=Tabard of the Wyrmrest Accord">  
<a href="http://www.wowhead.com/?search=Tattered Hexcloth Sack">

我需要在 = 之后但在 " 之前选择文本并将其打印在行尾,添加例如:

<a href="http://www.wowhead.com/?search=Superior Mana Oil">Superior Mana Oil</a>  
<a href="http://www.wowhead.com/?search=Tabard of Brute Force">Tabard of Brute Force</a>  
<a href="http://www.wowhead.com/?search=Tabard of the Wyrmrest Accord">Tabard of the   Wyrmrest Accord</a>  
<a href="http://www.wowhead.com/?search=Tattered Hexcloth Sack">Tattered Hexcloth Sack</a> 

我不确定通过 linux 命令行执行此操作的最佳方法(我猜可能是 sed/awk,但对它们不好),理想情况下我会喜欢一个脚本,我可以只提供文件名,例如./fixlink.sh brokenlinks.txt

【问题讨论】:

  • 尝试编写脚本并运行它。当/如果您遇到错误,请在此处发布并提供帮助。 “请为我编写脚本”类型的问题在这里不太受鼓励。

标签: linux text awk sed


【解决方案1】:

假设您可以在&lt;a 之后有一个或多个空格,并且在= 标志周围有零个或多个空格,那么以下应该可以工作:

$ cat in.txt
<a href="http://www.wowhead.com/?search=Superior Mana Oil">
<a href="http://www.wowhead.com/?search=Tabard of Brute Force">
<a href="http://www.wowhead.com/?search=Tabard of the Wyrmrest Accord">
<a href="http://www.wowhead.com/?search=Tattered Hexcloth Sack">
#
# The command to do the substitution
#
$ sed -e 's#<a[ \t][ \t]*href[ \t]*=[ \t]*".*search[ \t]*=[ \t]*\([^"]*\)">#&\1</a>#' in.txt
<a href="http://www.wowhead.com/?search=Superior Mana Oil">Superior Mana Oil</a>
<a href="http://www.wowhead.com/?search=Tabard of Brute Force">Tabard of Brute Force</a>
<a href="http://www.wowhead.com/?search=Tabard of the Wyrmrest Accord">Tabard of the Wyrmrest Accord</a>
<a href="http://www.wowhead.com/?search=Tattered Hexcloth Sack">Tattered Hexcloth Sack</a>

如果您确定没有多余的空格,则该模式将简化为:

s#<a href=".*search=\([^"]*\)">#&\1</a>#

sed 中,s 后跟任何字符(在本例中为#)开始替换。要替换的模式直到相同字符的第二次出现。因此,在我们的第二个示例中,要替换的模式是:&lt;a href=".*search=\([^"]*\)"&gt;。我用\([^"]*\) 表示任何非" 字符序列,并将其保存在反向引用\1 中(\(\) 对表示反向引用)。最后,由# 分隔的下一个标记是替换。 &amp; in sed 代表“whatever match”,在这种情况下是整行,\1 只匹配链接文本。

这又是模式:

's#<a[ \t][ \t]*href[ \t]*=[ \t]*".*search[ \t]*=[ \t]*\([^"]*\)">#&\1</a>#'

及其解释:

'                       quote so as to avoid shell interpreting the characters
s                       substitute
#                       delimiter
<a[ \t][ \t]*           <a followed by one or more whitespace
href[ \t][ \t]*=[ \t]*  href followed by optional space, = followed by optional space
".*search[ \t]*=[ \t]*  " followed by as many characters as needed, followed by
                        search, optional space, =, followed by optional space
\([^"]*\)               a sequence of non-" characters, saved in \1
">                      followed by ">
#                       delimiter, replacement pattern starts
&\1                     the matched pattern, followed by backreference \1.
</a>                    end the </a> tag
#                       end delimiter
'                       end quote

如果您真的确定总会有search= 后跟您想要的文字,您可以这样做:

$ sed -e 's#.*search=\(.*\)">#&\1</a>#'

希望对您有所帮助。

【讨论】:

  • 没有因为英雄的努力而投反对票,但是当一行代码需要 14 行解释时,下一个人维护它可能太聪明了。
  • LOL @Adam:我假设 OP 对正则表达式一无所知。再加上制作“稳健”的模式,导致了很长的解释。哦,好吧,我试过了。希望他学到了一些东西(如果他没有在我的帖子的 1/3 处感到无聊的话!)。 :-)
  • 当我试图解释一些技术细节时,我通常会发现我自己学到了一些东西 - 所以这绝不是白费力气。
【解决方案2】:
awk 'BEGIN{ FS="=" }
{
    o=$NF
    gsub(/\042>/,"",o)
    print $0, o"</a>"

}' file

输出

$ ./shell.sh
<a href="http://www.wowhead.com/?search=Superior Mana Oil"> Superior Mana Oil</a>
<a href="http://www.wowhead.com/?search=Tabard of Brute Force"> Tabard of Brute Force</a>
<a href="http://www.wowhead.com/?search=Tabard of the Wyrmrest Accord"> Tabard of the Wyrmrest Accord</a>
<a href="http://www.wowhead.com/?search=Tattered Hexcloth Sack"> Tattered Hexcloth Sack</a>

如果您不擅长某事,请阅读文档。这始终是解决方案的开始。如需了解 awk/gawk,请转至 doc

【讨论】:

    【解决方案3】:

    不错的 awk!但是

    sed -n 's|=\([^"].*\)"&gt;|&amp;\1&lt;/a&gt;|p'

    更短,并且会默默地删除不匹配的行。

    【讨论】:

      【解决方案4】:

      然后让我们在 sed 中进行。

      替换.sh

      #!/bin/bash
      #<a href="http://www.wowhead.com/?search=Tattered Hexcloth Sack">
      # =>
      #<a href="http://www.wowhead.com/?search=Tattered Hexcloth Sack">Tattered Hexcloth Sack</a>
      sed -r -e 's|(<a href=".*search=(.*))">|\1">\2</a>|' $1
      

      ./replace.sh input.txt

      【讨论】:

        【解决方案5】:

        使用 sed:

        sed 's/\(.*search=\)\(.*\)\(".*\)/\1\2\3\2<\/a>/' brokenlinks.txt
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-01-29
          相关资源
          最近更新 更多