如何在Linux中对grep的管道输出进行子串?

时间:2012-01-28 23:34:50

标签: linux bash curl cygwin piping

我正在尝试编写一个脚本来自动登录Drupal网站,使其进入维护模式。这是我到目前为止所做的,而grep让我回到了我想要的路线。

curl http://www.drupalwebsite.org/?q=user | grep '<input type="hidden" name="form_build_id" id="form-[a-zA-Z0-9]*" value="form-[a-zA-Z0-9]*"  />'

现在我是一个Linux新手,我正在使用Cygwin和BASH。然后,我将如何管道输出并使用命令从grep生成的输出中获取id属性的值?我稍后会使用这个子字符串来执行另一个curl请求来实际提交登录信息。

我正在考虑使用expr,但我真的不明白我将如何告诉expr“哦,这个stdin数据我希望你以这种方式操纵”。似乎我能做到这一点的唯一方法是在变量中保存grep输出,然后将变量提供给expr。

2 个答案:

答案 0 :(得分:1)

您可以使用grep选项再次使用-o。可能还有两个连续的grep来过滤掉周围的id="..."部分。

   -o, --only-matching
          Print only the matched (non-empty) parts  of  a  matching  line,
          with each such part on a separate output line.

答案 1 :(得分:1)

使用sed修剪您从grep获得的结果,即

编辑:添加了myID变量,使用您喜欢的任何名称。

myID=$( 
  curl http://www.drupalwebsite.org/?q=user \
  | grep '<input type="hidden" name="form_build_id" id="form-[a-zA-Z0-9]*" value="form-[a-zA-Z0-9]*"  />' \
  | sed 's/^.* id="//;s/" value=.*$//'
)


#use ${myID} later in script
printf "myID=${myID}\n"

第一部分删除字符串的“前”部分,一切都移至id=",而第二部分删除每个" value= ....

请注意,您可以将sed中的多个子替换操作链接在一起,方法是将它们与';'分开。

<强> EDIT2 此外,一旦你使用sed,没有理由使用grep,试试这个:

myID=$( 
  curl http://www.drupalwebsite.org/?q=user \
  | sed -n '\@<input type="hidden" name="form_build_id" id="form-[a-zA-Z0-9]*" value="form-[a-zA-Z0-9]*"  />@{
       s\@^.* id="@@
       s\@" value=.*$@@p
   }'
)

(这是一个习惯于删除不必要的进程的好习惯。在这种情况下可能无关紧要,但是如果你到达编写将在一小时内执行1000次的代码的地方,那么需要额外的grep当你不需要它时,就会创建1000个不需要创建的额外进程。)

你可能不得不逃避'&lt;和&gt;'比如'\&lt; &GT;”或者,最坏的情况'[&lt;] [&gt;]'。

我现在使用'@'作为reg-ex替换分隔符,以避免必须转义srch-target字符串中的任何'/'字符。我在整个例子中继续使用它,只是为了保持一致。对于某些seds,你告诉他们你使用的是非标准分隔符,因此在每个sed代码块的前面都是前导\ _。

-n表示“不默认打印每一行输入”,因此,我们必须在末尾添加'p',这意味着打印当前缓冲区。

最后,我不确定你的正则表达式,尤其是-[a-zA-Z0-9]*,这意味着前一个字符(或本例中的字符类)中的零个或多个。通常情况下,想要至少一个字母数字的人会使用-[a-zA-Z0-9][a-zA-Z0-9]*,是或[[:alnum:]][[:alnum:]]*,但我不清楚你的数据是否足够肯定。

我希望这会有所帮助。