linux Awk模式匹配

lnvxswe2  于 11个月前  发布在  Linux
关注(0)|答案(8)|浏览(182)

我想打印

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来提取兴趣区。

nnsrf1az

nnsrf1az1#

我不确定我是否理解了你的“单行数据”评论,但如果这是在一个文件中,你可以这样做:

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命令分别:

  • 从第一个引号开始。
  • 将名称和值之间的部分替换为“="。
  • 删除值结束引号之后的所有内容(包括该引号)。
idfiyjo8

idfiyjo82#

这部分应该是对Pax的回答的评论,但是对于那个小盒子来说,它有点长。我想“单行数据”意味着你的变量中没有任何换行符?那么这将起作用:

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

字符串
有趣的地方:--n意味着默认情况下不打印-我们将在最后说明何时使用p打印。

  • -r表示扩展正则表达式
  • /<input/在开始时确保我们甚至不必费心处理不包含所需模式的行
  • 最后的\n是为了确保所有记录都在单独的行上结束-任何原始的换行符仍然会在那里,最快的摆脱它们的方法是添加一个“|你可以使用sed魔法,但是你在输入后30秒内无法理解它。

我可以想到在awk中实现这一点的方法,但这实际上是sed(或perl!)的工作。

uqdfh47h

uqdfh47h3#

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

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

字符串

jum4pzuy

jum4pzuy4#

使用perl

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

字符串

egdjgwm8

egdjgwm85#

在我看来,解析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

字符串
产生你想要的输出

7fhtutme

7fhtutme6#

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
}

字符串

tp5buhyn

tp5buhyn7#

awk和sed等工具可以与XMLStarletHTML Tidy一起使用来解析HTML。

vc9ivgsu

vc9ivgsu8#

下面是一个简短的awk oneliner使用bash:

awk 'BEGIN{ FS="\""; RS="<";}/\=/{print $2," = ", $4;}' <(printf "%s" ${info})

字符串
说明:
RS="<”--将文本分成记录(-行)
FS=""”--将记录分为字段,

/\=/ -- choose lines containing =


{print $2,”=“,$4;} --打印第二个和第四个字段,用空格和=分隔

相关问题