Awk模式匹配

时间:2009-09-22 14:15:12

标签: regex linux bash awk

我想打印

userId = 1234
userid = 12345
timestamp = 88888888
js = abc

来自我的数据

messssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
<input name="userId" value="1234" type="hidden"> messsssssssssssssssssss
<input name="userid" value="12345" type="hidden"> messssssssssssssssssss
<input name="timestamp" value="88888888" type="hidden"> messssssssssssss
<input name="js" value="abc" type="hidden"> messssssssssssssssssssssssss
messssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss

我怎样才能用AWK(或其他)做到这一点?假设我的数据存储在“$info”变量(单行数据)中。

编辑:单行数据我的意思是所有数据都表示如下

messss...<input name="userId" value="1234" type="hidden">messsss...<input ....>messssssss

所以我不能用grep来提取兴趣部分。

7 个答案:

答案 0 :(得分:4)

我不确定我理解您的“单行数据”评论,但如果这是在一个文件中,您可以执行以下操作:

cat file
    | grep '^<input '
    | sed 's/^<input name="//'
    | sed 's/" value="/ = /'
    | sed 's/".*$//'

这是cut'n'paste版本:

cat file | grep '^<input ' | sed 's/^<input name="//' | sed 's/" value="/ = /' | sed 's/".*$//'

这转变:

messssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
<input name="userId" value="1234" type="hidden"> messsssssssssssssssssss
<input name="userid" value="12345" type="hidden"> messssssssssssssssssss
<input name="timestamp" value="88888888" type="hidden"> messssssssssssss
<input name="js" value="abc" type="hidden"> messssssssssssssssssssssssss
messssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss

非常高兴地进入:

userId = 1234
userid = 12345
timestamp = 88888888
js = abc

grep只会在sed命令时分别提取所需的行:

  • 剥离第一个引用。
  • 使用“=”替换名称和值之间的部分。
  • 删除价值结束报价后的所有内容(包括该报价)。

答案 1 :(得分:3)

这一部分可能应该是对Pax答案的评论,但这个小盒子有点长。我在想'单行数据'意味着你的变量根本没有换行符?然后这将工作:

echo "$info" | sed -n -r '/<input/s/<input +name="([^"]+)" +value="([^"]+)"[^>]*>[^<]*/\1 = \2\n/gp'

关于有趣位的说明:   - -n表示默认情况下不打印 - 我们会说最后何时使用p进行打印。

  • -r表示扩展正则表达式

  • 开头的
  • /<input/确保我们甚至懒得处理不包含所需模式的行

  • 最后\n确保所有记录都以不同的方式结束 - 任何原始的新行仍然存在,而摆脱它们的最快方法就是“ | grep。'最后 - 你可以使用一些sed魔法,但在输入后30秒你将无法理解它。

我可以想办法在awk中做到这一点,但这对sed(或perl!)来说真是一份工作。

答案 2 :(得分:2)

要处理包含多行的变量,需要将变量名称放在双引号中:

echo "$info"|sed 's/^\(<input\( \)name\(=\)"\([^"]*\)" value="\([^"]*\)"\)\?.*/\4\2\3\2\5/'

答案 3 :(得分:2)

使用perl

cat file | perl -ne 'print($1 . "=" . $2 . "\n") if(/name="(.*?)".*value="(.*?)"/);'

答案 4 :(得分:1)

IMO,解析HTML应该使用适当的HTML / XML解析器。例如,Ruby有一个很好的软件包,Nokogiri,用于解析HTML / XML:

ruby -e '
    require "rubygems"
    require "nokogiri"
    doc = Nokogiri::HTML.parse(ARGF.read)
    doc.search("//input").each do |node|
        atts = node.attributes
        puts "%s = %s" % [atts["name"], atts["value"]]
    end
' mess.html

生成你之后的输出

答案 5 :(得分:0)

AWK:

BEGIN {
  # Use record separator "<", instead of "\n".
  RS = "<"
  first = 1
}

# Skip the first record, as that begins before the first tag
first {
  first = 0
  next
}

/^input[^>]*>/ { #/
  # make sure we don't match outside of the tag
  end = match($0,/>/)

  # locate the name attribute
  pos = match($0,/name="[^"]*"/)
  if (pos == 0 || pos > end) { next }
  name = substr($0,RSTART+6,RLENGTH-7)

  # locate the value attribute
  pos = match($0,/value="[^"]*"/)
  if (pos == 0 || pos > end) { next }
  value = substr($0,RSTART+7,RLENGTH-8)

  # print out the result
  print name " = " value
}

答案 6 :(得分:0)

像awk和sed这样的工具可以与XMLStarletHTML Tidy一起使用来解析HTML。