題 從grep結果中獲取子字符串


給定一個日誌文件,我通常會這樣做:

grep 'marker-1234' filter_log

在模式中使用“或”或“無”有什麼區別?

上面的grep命令將產生數千行;我想要什麼。在這些行中,我經常會有一大塊數據。有時,我使用awk打印出我追求的字段。在這種情況下,日誌格式發生變化,我不能單獨依賴位置,更不用說,實際記錄的數據可以向前推送位置。

為了使這個可以理解,讓我們說日誌行包含一個IP地址,這就是我所追求的,所以我可以稍後將其管道進行排序和唯一,並得到一些計數。

一個例子可能是:

2010-04-08 some logged data, indetermineate chars - [marker-1234] (123.123.123.123) from: foo@bar.example.com to bar@foo.example.com [stat-xyz9876]

第一個grep命令會給我幾千條如上所述的行,從那裡開始,我想將它傳遞給某些東西,可能 sed,可以拉出圖案,並只打印圖案。

對於此示例,使用IP地址就足夠了。我試過了。是 sed 無法理解[0-9] {1,3}。作為一種模式?我不得不[0-9] [0-9] [0-9]。在整個模式創建之前,它產生了奇怪的結果。

這不是特定於IP地址,模式會改變,但我可以將其用作學習模板。

謝謝你們。


4
2018-04-09 01:18


起源


這聽起來與編程有關,甚至是簡單的bash命令 grep的 和 AWK 在我看來更好地回答stackoverflow。 - Josh K
@Josh:SU有很多可以處理這類問題的linux命令行戰士,歡迎來到這裡。它可能是適合任何一個網站的問題之一,所以這完全取決於提問者。 - quack quixote
我給了它一些想法,說實話,我不知道在哪裡發布它。我選擇了網站的名稱,認為SO更通用,SU更像是管理類型的東西。我發現大多數快速shell腳本都是管理員相關的。當然,你出於某種原因進入大型tcl或bash獨家項目,在這種情況下,我會將其縮小到編程相關並發佈到SO。這更像是一個班輪,蘇似乎是一個很好的家。對不起,如果我在錯誤的位置發布,但在某些情況下似乎是灰色區域。 - user17245
@allentown:實際上Server Fault是更多管理類型的東西;超級用戶是更多最終用戶的東西。 (但是高級用戶最終用戶。)無論如何,這個問題可能會受到SO / SF / SU的歡迎。你已經接受了答案,所以如果你滿意,你可以稱之為完成。或者如果您願意,我們可以將其遷移到SO / SF;只是標記它以供主持人注意並告訴我們在哪裡發送它。謝謝! - quack quixote
@quack:沒關係,我只是覺得可以找到更好的答案,但似乎已經找到了。 - Josh K


答案:


我不知道你在用什麼操作系統,但在FreeBSD 7.0+ grep上有一個 -o 選項僅返回與模式匹配的部分。所以你可以
grep "marker-1234" filter_log | grep -oE "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"

返回'filter_log'中僅包含IP地址的列表...

這適用於我的系統,但同樣,我不知道你的grep版本支持什麼。


7
2018-04-09 02:28



我認為這裡的所有答案都是很好的學習方法,並以相同的答案接近最終結果。我特別喜歡這個,因為它很容易記住,只是管道鏈接多個grep命令。在Mac OS X上,我似乎有-o選項,當然也經常使用-E選項。謝謝您的回复 - user17245


你可以在一個人中完成所有這些 awk 命令。無需使用任何其他工具

$ awk '/marker-1234/{for(o=1;o<=NF;o++){if($o~/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)print $o }  }' file
(123.123.123.123)

3
2018-04-09 02:44



謝謝,這確實有效,awk有時可能會傷害你的頭部,但我已經習慣了FOO ....外殼中快速的東西的一個線性方面。很強大。 - user17245


你可以縮短第二個 grep 有點像這樣:

grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'

要回答第一個問題,雙引號允許shell執行各種操作,如變量擴展,但保護某些元字符不需要轉義。單引號可防止shell執行這些擴展。不使用引號會讓事情大開眼界。

$ empty=""
$ text1="some words"
$ grep $empty some_file
(It seems to hang, but it's just waiting for input since it thinks "some_file" is 
the pattern and no filename was entered, so it thinks input is supposed to come
from standard input. Press Ctrl-d to end it.)
$ grep "$empty" some_file
(The whole file is shown since a null pattern matches everything.)
$ grep $text1 some_file
grep: words: No such file or directory
some_file:something
some_file:some words
(It sees the contents of the variable as two words, the first is seen as the 
pattern, the second as one file and the filename as a second file.)
$ grep "$text1" some_file
some_file:some words
(Expected results.)
$ grep '$text1' some_file
(No results. The variable isn't expanded and the file doesn't contain a
string that consists of literally those characters (a dollar sign followed
by "text1"))

您可以在“QUOTING”部分了解更多信息 man bash


2
2018-04-09 04:16



好記,謝謝。我需要更好地處理這個問題,同時注意到IFS,前幾天我對此非常感興趣,但確實設法讓IFS玩得很好。當你有IFS設置並忘記它時,這是一個可怕的事情,想知道wtf會持續一個小時。 - user17245
養成永遠保存價值的習慣是個好主意 IFS 並儘快恢復: saveIFS="$IFS"; IFS=","; do_something; IFS="$saveIFS"; do_other_stuff - Dennis Williamson
+1對正則表達式的良好調用,我沒有太多使用它,所以我傾向於有點低效。 - Chris S


抬頭看 xargs 命令。你應該能夠做到這樣的事情:

grep'marker-1234'filter_log | xargs grep“(”| cut -c1-15

這可能不完全是,但是 xargs 是您要使用的命令


1
2018-04-09 01:38