簡體   English   中英

在GNU Grep或其他標准bash命令中,是否可以從正則表達式獲取結果集?

[英]In GNU Grep or another standard bash command, is it possible to get a resultset from regex?

考慮以下:

var="text more text and yet more text"
echo $var | egrep "yet more (text)"

應該可以將正則表達式的結果作為字符串: text

但是,我目前尚無辦法在bash中使用grep或其兄弟姐妹執行此操作。

在perl,php或類似的正則表達式引擎中:

$output = preg_match('/yet more (text)/', 'text more text yet more text');
$output[1] == "text";

編輯:要詳細說明為什么我不能只使用多個正則表達式,最后我將擁有一個包含多個正則表達式的正則表達式(如下圖所示),因此我需要能夠全部使用它們。 這也消除了使用超前/向后看的選項(因為它們都是可變長度的)

egrep -i "([0-9]+) +$USER +([0-9]+).+?(/tmp/Flash[0-9a-z]+) "

直接根據lsof輸入的示例輸入(此輸入數據的$ USER替換為“ j”):

npviewer. 17875          j   11u      REG                8,8 59737848     524264 /tmp/FlashXXu8pvMg (deleted)
npviewer. 17875          j   17u      REG                8,8 16037387     524273 /tmp/FlashXXIBH29F (deleted)

最終目標是每行cp /proc/$var1/fd/$var2 ~/$var3 ,最終“下載” Flash文件(Flash曾經存儲在/ tmp中,但它們將其刪除)

到目前為止,我已經:

#!/bin/bash
regex="([0-9]+) +j +([0-9]+).+?/tmp/(Flash[0-9a-zA-Z]+)"

echo "npviewer. 17875          j   11u      REG                8,8 59737848     524264 /tmp/FlashXXYOvS8S (deleted)" |
sed -r -n -e " s%^.*?$regex.*?\$%\1 \2 \3%p " |
while read -a array
do
   echo /proc/${array[0]}/fd/${array[1]} ~/${array[2]}
done

它會截斷要返回的第一個值的前幾位,而我對sed並不十分了解,以了解出了什么問題。

下載Flash 10.2+視頻(包括加密的視頻)的最終結果:

#!/bin/bash
lsof | grep "/tmp/Flash" | sed -r -n -e " s%^.+? ([0-9]+) +$USER +([0-9]+).+?/tmp/(Flash[0-9a-zA-Z]+).*?\$%\1 \2 \3%p " |
while read -a array
do
   cp /proc/${array[0]}/fd/${array[1]} ~/${array[2]}
done

編輯:查看我的其他答案,以獲得更簡單的僅bash解決方案。


因此,這里的解決方案使用sed獲取正確的組並將其拆分 您以后仍然必須使用bash來閱讀它們。 (以這種方式,它僅在組本身不包含任何空格的情況下才起作用-否則,我們必須通過將$IFS設置為此值來使用另一個分隔符和補丁read 。)

#!/bin/bash
USER=j
regex=" ([0-9]+) +$USER +([0-9]+).+(/tmp/Flash[0-9a-zA-Z]+) "


sed -r -n -e " s%^.*$regex.*\$%\1 \2 \3%p " |
while read -a array
do
   cp /proc/${array[0]}/fd/${array[1]} ~/${array[2]}
done

請注意,我必須調整您的最后一個正則表達式組以允許使用大寫字母,並在開頭添加一個空格以確保捕獲整個數字塊。 另外,這里\\b (字數限制)也可以使用。

啊,我忘了提到您應該將文本通過管道傳遞到此腳本,如下所示:

 ./grep-result.sh  < grep-result-test.txt 

(前提是您的文件是這樣命名的)。 相反,您可以在sed調用之后(在|之前)添加< grep-result-test ,或在行前添加cat grep-result-test.txt |


它是如何工作的?

  • sed -r -n以擴展正則表達式模式調用sed,並且不會自動打印任何內容。
  • -e " s%^.*$regex.*\\$%\\1 \\2 \\3%p "給出sed程序,它由單個s命令組成。

    • 我使用%而不是普通的/作為參數分隔符,因為/出現在正則表達式中,並且我不想對其進行轉義。
    • 要搜索的正則表達式以^.*為前綴,並以.*$結尾,以捕獲整行(並避免打印其余行)。

      請注意,此.*貪婪,因此我們必須在正則表達式中插入一個空格,以避免它也捕獲第一個數字組的開頭。

    • 替換文本包含三個括號組,以空格分隔。
    • 命令末尾的p標志指示替換后打印出模式空間。 由於我們抓住了整行,因此模式空間僅包含替換文本。
  • 因此,您的示例輸入的sed輸出是這樣的:

     5 11 /tmp/FlashXXu8pvMg 5 17 /tmp/FlashXXIBH29F 

    顯然,這對於重用更為友好。

  • 現在,我們將此輸出通過管道傳遞給while循環。

    • read -a array從標准輸入(由於管道的緣故,是sed的輸出)中讀取一行,將其拆分為單詞(在空格,制表符和換行符處),並將這些單詞放入數組變量中。

      我們還可以read var1 var2 var3 (最好使用更好的變量名),然后將前兩個單詞分別放在$var1$var2 ,其余的則放在$var3

    • 如果read成功讀取一行(即不是文件末尾),則執行循環主體:
      • ${array[0]}被擴展到數組的第一個元素,並且類似地。
    • 輸入結束時,循環也結束。

使用grep或從shell提示符/腳本調用的其他工具是不可能的,因為子進程無法修改其父進程的環境。 如果您使用的是bash 3.0或更高版本,則可以使用進程內正則表達式。 語法為perl-ish(=〜),可通過$ BASH_REMATCH [x]獲得匹配組,其中x是匹配組。

創建sed解決方案后,我還想嘗試Mark建議的純bash方法。 對我來說,它工作得很好。

#!/bin/bash

USER=j
regex=" ([0-9]+) +$USER +([0-9]+).+(/tmp/Flash[0-9a-zA-Z]+) "

while read 
do
    if [[ $REPLY =~ $regex ]]
    then
        echo cp /proc/${BASH_REMATCH[1]}/fd/${BASH_REMATCH[2]} ~/${BASH_REMATCH[3]}
    fi
done

(如果您對此表示支持,則應該考慮也對Marks答案進行支持,因為這本質上是他的想法。)

與之前相同:將要過濾的文本通過管道傳遞到此腳本。


它是如何工作的?

  • 正如Mark所說的, [[ ... ]]特殊條件構造支持二進制運算符=~ ,它將其右操作數(在參數擴展之后)解釋為擴展的正則表達式(就如我們所願),並與左操作數匹配反對。 (我們再次在前面添加了一個空格,以避免僅匹配最后一位。)
  • 當正則表達式匹配時, [[ ... ]]返回0(= true),並將與單個組匹配的部分(以及整個表達式)放入數組變量BASH_REMATCH
  • 因此,當正則表達式匹配時,我們輸入then塊,然后在其中執行命令。
  • 同樣,這里的${BASH_REMATCH[1]}是對數組元素的數組訪問,該元素對應於第一個匹配組。 [0]將是整個字符串。)

另一個注意事項:我的兩個腳本都接受多行輸入,並在匹配的每一行上工作。 不匹配的行將被忽略。 如果只輸入一行,則不需要循環, if read ; then ...很簡單if read ; then ... if read ; then ...甚至read && [[ $REPLY =~ $regex ]] && ...就足夠了。

echo "$var" | pcregrep -o "(?<=yet more )text"

好吧,對於您的簡單示例,您可以執行以下操作:

var="text more text and yet more text"
echo $var | grep -e "yet more text" | grep -o "text"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM