我有一个名为'res'的文件,它是一行字符串中的29374个http数据字符。在它里面,有几个http链接,但我只想显示以'/ idNNNNNNNNN'结尾的那些,其中N是一个数字。事实上,我只对字符串'idNNNNNNNNN'感兴趣。 我试过了:
cat res | sed -n '0,/.*\(id[0-9]*\).*/s//\1/p'
但我得到了整个文件。 你知道办法吗?
答案 0 :(得分:2)
perl -n -E 'say $1 while m!/id(\d{9})!g' input-file
应该有效。这恰好是9位数;那就是上面的{9}
。您可以匹配8或9({8,9}
),8或更多({8,}
),最多9({0,9}
)等。
这项工作的例子:
$ echo -n 'junk jumk http://foo/id231313 junk lalala http://bar/id23123 asda' | perl -n -E 'say $1 while m!id(\d{0,9})!g'
231313
23123
当然,这是0到9的变体。
如果您遇到的是5.10之前的perl,请使用-e
代替-E
和print "$1\n"
代替say $1
。
首先是Perl的两个命令行参数。 -n
告诉Perl读取命令行上给出的标准输入或文件的输入,逐行,将$_
设置为每一行。 $_
是perl的很多东西的默认目标,包括正则表达式匹配。 -E
只是告诉Perl下一个参数是Perl一行,使用新的语言功能(与-e
不使用5.10扩展名。)
所以,看一个衬垫:say
意味着打印出一些值,然后是换行符。 $1
是第一个正则表达式捕获(捕获是由正则表达式中的括号进行的)。 while
是一个循环结构,您可能熟悉它。 m
是匹配运算符,!
之后是正则表达式分隔符(通常,您在此处看到/
,但由于该模式包含/
,因此更容易使用否则,您不必将/
转义为\/
)。 /id(\d{9})
是要匹配的正则表达式。请注意,分隔符为!
,因此/
并不特殊,它只与文字/
匹配。括号形成一个捕获组,因此$1
将是数字。 !
是分隔符,后跟g
,这意味着匹配尽可能多的次数(而不是一次)。这使得它获取行中的所有URL,而不仅仅是第一个。只要匹配,m
运算符将返回一个真值,因此循环将继续(并运行say $1
,打印出匹配)。
我认为这是仅使用sed执行此操作的一种方法。更复杂!
echo 'junk jumk http://foo/id231313 junk lalala http://bar/id23123 asda' | \
sed 's!http://!\nhttp://!g' | \
sed 's!^.*/id\([0-9]*\).*$!\1!'
答案 1 :(得分:0)
cat res | perl -ne 'chomp; print "$1\n" if m/\/(id\d*)/'
答案 2 :(得分:0)
问题是sed和grep和awk在线上工作,而你只有一行。因此,您可能需要拆分,以便拥有多行 - 然后您可以使普通工具正常工作。
tr ':' '\012' < res |
sed -n 's%.*/\(id[0-9][0-9]*\).*%\1%p'
这会利用包含冒号的网址,并使用tr
将冒号映射到换行符,然后使用sed
选取任何斜线,然后选择id
和一个或多个数字,后跟任何东西,并打印出id和数字字符串(仅)。由于这些只出现在URL中,因此它们每行只出现一个并且相对靠近行的起点。
答案 3 :(得分:0)
这是一个仅使用sed
的一次调用的解决方案:
sed -n 's| |\n|g;/^http/{s|http://[^/]*/id\([0-9]*\)|\1|;P};D' inputfile
说明:
s| |\n|g;
- 分而治之/^http/{
- 如果模式空间以“http”开头
s|http://[^/]*/id\([0-9]*\)|\1|;
- 捕获ID P
- 打印第一个换行符之前的字符串};
- 结束如果D
- 删除第一个换行符之前的字符串,无论它是否包含“http”修改强>
此版本使用相同的技术但更具选择性。
sed -n 's|http://|\n&|g;/^\n*http/{s|\n*http://[^/]*/id\([0-9]*\)|\1\n|;P};D' inputfile