2016-10-01 50 views
0

使用shell我想搜索並打印只有子字符串的下一個單詞。如何從grep中提取單詞結果在shell中?

例如日誌文件有行「今天是星期一,這是:1234,所以我在」。

if grep -q "this is :" ./logfile; then 
    #here i want to print only sub-string with next word i.e. "this is:1234" 
    #echo ??? 
fi 
+0

文件需要多長時間?如果它很短,那麼在本機shell中執行搜索可能會更快,而不是產生外部工具('grep','sed','awk'等),儘管這些工具通常會在處理內容時更快地處理內容支付。 –

+0

順便說一句,外層的'if grep -q'可能是一個壞主意 - 意味着你正在讀取文件兩次,一次檢查其內容,然後再次讀取其內容。如果你要運行一個外部命令,最好使用'if result = $(that-c​​ommand);然後...'同時捕獲輸出和檢查退出狀態。如果命令沒有根據是否匹配設置退出狀態,那麼'if result = $(that-c​​ommand)&& [-n「$ result」];那麼'可能會更有意義。 –

回答

0

您可以使用正則表達式以look-behind,如果你想只有一個字:

$ grep --perl-regexp -o '(?<=(this is:))(\S+)' ./logfile 
1234 

如果你想同時,那麼就:

$ grep --perl-regexp -o 'this is:\S+' ./logfile 
this is:1234 

-o選項指示grep僅返回匹配部分。

在上面的命令中,我們假定「單詞」是一個非空格字符序列。您可以根據自己的需要進行調整。

1

可以使用sed\1\(..\)顯示匹配的字符串:

sed 's/.*\(this is:[0-9a-zA-Z]*\).*/\1/' logfile 

編輯:上述命令是隻對1行輸入罰款。

當你有更多行的文件,你只想打印匹配的行:

sed -n 's/.*\(this is:[0-9a-zA-Z]*\).*/\1/p' logfile 

當你有一個大的文件,只希望看到的第一場比賽,你可以將這個命令與head -1,但你想在第一場比賽後停止掃描/解析。您可以使用q退出,但您只想在比賽結束後退出。

sed -n '/.*\(this is:[0-9a-zA-Z]*\).*/{s//\1/p;q}' 
+0

如果你修改了這個也消除了其他每一行,並在找到一個匹配後退出,我想我們會被設置。 –

+0

@Charles:檢查。 –

+0

看起來不錯。 –

0

你可以找的一切行動,但不包括像這樣的一個空格:

[]介紹了一套您正在尋找的字符和^在開始補充設置,所以你正在尋找的字符集是一個空白空間,但補充,即不是空白。 +表示必須至少有一個或多個這樣的字符。

-E告訴grep使用擴展正則表達式,而-o表示僅打印匹配的部分。

+0

我建議使用'[^ ​​[:space:]]'也停止在製表符&c。 –

+0

@CharlesDuffy是的,這是一個明顯的進步 - 謝謝。 –

0

如果你有GNU擴展的系統(但不確定它與可選PCRE支持編譯),考慮:

if result=$(grep -E -m 1 -o 'this is:[^[:space:]]+' logfile); then 
    echo "value is: ${result#*:}" 
fi 

${varname#value}展開爲varname內容,但與value從剝離如果有的話開始。因此,${result#*:}將所有內容刪除至result中的第一個冒號。

但是,對於沒有非POSIX選項-o-m的系統,這可能不起作用。


如果你想支持非GNU系統,awk是值得考慮的一個工具:不同需要不可移植的擴展答案(如grep -P),這應該在任何現代平臺(與GNU AWK,近期BSD AWK測試工作,和mawk;也沒有警告與gawk --posix --lint):

# note that the constant 8 is the length of "this is:" 
# GNU awk has cleaner syntax, but trying to be portable here. 
if value=$(awk ' 
    BEGIN { matched=0; }  # by default, this will trigger END to exit as failure 
    /this is:/ { 
    match($0, /this\ is:([^[:space:]]+)/); 
    print substr($0, RSTART+8, RLENGTH-8); 
    matched=1;    # tell END block to use zero exit status 
    exit(0);    # stop processing remaining file contents, jump to END 
    } 
    END { if(matched == 0) { exit(1); } } 
'); then 
    echo "Found value of $value" 
else 
    echo "Could not find $value in file" 
fi