2017-08-02 93 views
2

我有兩個文件,我試圖運行find/grep/fgrep。我一直在嘗試幾個不同的命令,試圖得到如下結果:從文件b中找出文件a中的單詞,並從文件a輸出丟失的單詞匹配

文件

hostnamea 
hostnameb 
hostnamec 
hostnamed 
hostnamee 
hostnamef 

文件B

hostnamea-20170802 
hostnameb-20170802 
hostnamec-20170802.xml # some files have extensions 
020214-_hostnamed-20170208.tar # some files have different extensions and have different date structure 
HOSTNAMEF-20170802 

*有關文件 - 日期= 20170802 - 大多數都有這樣的日期格式 - 一些有不同的日期格式*

FileA是我的控制文件 - 我想搜索整個單詞hostnamea-f和匹配hostnamea-f在fileb中,並將來自filea的不匹配項輸出到終端上的輸出中,以便在shell腳本中使用。

對於這個例子,我做到了hostnamee不在fileb中。我想運行一個fgrep/grep/awk - 無論如何可以工作 - 並只輸出filea中缺失的hostnamee

我可以得到這個工作,但它並不特別做我所需要的,如果我交換它,我什麼也得不到。

[email protected]:/netops/backups/scripts$ fgrep -f filea fileb -i -w -o 
hostnamea 
hostnameb 
hostnamec 
hostnamed 
HOSTNAMEF 

很酷 - 我得到了File-B中的匹配,但是如果我嘗試反轉它,該怎麼辦?

[email protected]:/netops/backups/scripts$ fgrep -f fileb filea -i -w -o 
[email protected]:/netops/backups/scripts$ 

我嘗試了幾個不同的命令,但似乎無法弄清楚。我使用-i來忽略大小寫,-w匹配整個單詞和-o

我找到了一些解決方法,但希望有一個更優雅的方法來做到這一點,使用單個命令awk,egrep, fgrep或其他。

[email protected]:/netops/backups/scripts$ fgrep -f filea fileb -i -w -o > test 
[email protected]:/netops/backups/scripts$ diff filea test -i 

5D4 < hostnamee

+0

在我的真實情況下 - 上面的這個工作甚至不像上面的例子那樣工作。我在文件名中也有 - 和_,並且它似乎沒有給出與上述相同的結果。 –

+0

你想'HOSTNAMEF'被認爲是匹配'hostnamef'嗎?即不區分大小寫? – Yunnosch

+0

是的 - 在這種情況下,一些備份文件的例子 - 在大寫完成,而我的主機文件都是小寫 - 所以HOSTNAMEF應=主機名 –

回答

3

您可以

  • 尋找 「只-匹配」,即-o,一個在B
  • 使用的模式來尋找結果a,即-f-
  • 只列出不匹配的東西,即-v

代碼:

grep -of a.txt b.txt | grep -f- -v a.txt 

輸出:

hostnamee 
hostnamef 

不區分大小寫代碼:

grep -oif a.txt b.txt | grep -f- -vi a.txt 

輸出:

hostnamee 

編輯:
爲了響應Ed Morton的有趣輸入,我已經使示例輸入有點「nastier」來測試針對子字符串匹配和正則字符活動字符(例如, 「」):

A.TXT:

hostnamea 
hostnameb 
hostnamec 
hostnamed 
hostnamee 
hostnamef 
ostname 
lilihostnamec 
hos.namea 

b.txt:

hostnamea-20170802 
hostnameb-20170802 
hostnamec-20170802.xml # some files have extensions 
020214-_hostnamed-20170208.tar # some files have different extensions and have different date structure 
HOSTNAMEF-20170802 
lalahostnamef 
hostnameab 
stnam 

這使得事情變得更加有趣。 我提供這個不區分大小寫的解決方案:

grep -Fwoif a.txt b.txt | grep -f- -Fviw a.txt 
  • 額外-F,意思是 「沒有正則表達式的招數」
  • 額外-w,意爲 「全字匹配」

我找到輸出相當滿意,假設接受以下「要求」更改:
「a」中的主機名僅與「b」的部分匹配,如果全部相鄰_ (和其他「單詞主人公」總是被認爲是主機名的一部分。
(請注意,hostnamed的附加輸出行現在不再在「b」中找到,因爲在「b」中,它前面有一個_)。
要匹配可能出現的有效主機名,通過其他單詞字符,「a」中的列表將不得不明確地命名這些變體。例如。必須列出「_hostnamed」才能在輸出中沒有「主機名」。 (運氣好的話,OP甚至可以接受,那麼推薦使用這個擴展的解決方案;爲了抵抗「EdMortonish陷阱」的可靠性,Ed,請認爲這是對你有趣的輸入的補充,但這並不意味着任何負面的。)

輸出爲「骯髒」 a和b:

hostnamed 
hostnamee 
ostname 
lilihostnamec 
hos.namea 

我不知道改變的處理的_是否仍然符合有機磷農藥的目標(如果沒有,OP的範圍內第一個不區分大小寫的解決方案滿足)。 _是「字母字符」的一部分,可用於「全字匹配」-w。正如Ed Morton所提到的,更詳細的正則表達式控制在某些方面已經超越了grep,因此使用awk,perl(sed用於受虐狂的大腦練習,我喜歡的那種)是適當的。

在Windows上使用GNU grep 2.5.4。 文件a.txt和b。txt有你的內容,但我確定他們有UNIX行結束,這很重要(至少對於a而言,可能不適用於b)。

+0

grep -of file1 file2 -i | grep -f- -v file1 -i(這似乎是用您的命令示例添加忽略大小寫的正確方法) –

+0

我提供了一個不區分大小寫的版本(在注意到您的評論問題之前)。 – Yunnosch

+0

這將做到 - 謝謝你的答案 –

2
$ cat tst.awk 
NR==FNR { 
    gsub(/^[^_]+_|-[^-]+$/,"") 
    hostnames[tolower($0)] 
    next 
} 
!(tolower($0) in hostnames) 

$ awk -f tst.awk fileB fileA 
hostnamee 

$ awk -f tst.awk b.txt a.txt 
hostnamee 
ostname 
lilihostnamec 
hos.namea 

在上面的唯一前提是,你的主機名不包含下劃線和任何上線的最後-後的日期。如果情況並非如此,那麼fileB中的可選主機名前綴和後綴字符串有更好的定義,那麼只需調整gsub()即可使用適當的正則表達式。

+0

嗯,還需要一個假設,真是可惜,但基於這個假設,它和我的解決方案一樣有效(基於我的假設),謝謝你提供一個替代角度,我想我看到了一個非常早期的,幾乎透徹的評論,預測了我們兩個人遇到的問題。可惜它被刪除了。 – Yunnosch

+0

它只需要一個假設,因爲OP尚未告訴我們任何方式來區分主機名與前綴或後綴。必須有一個強大的方法,但我們需要OP來告訴我們這是什麼。它不能假設的是主機名的值,這就是爲什麼它比grep解決方案更好。 (提高健壯性的證據是,在greps +管道解決方案時,這不會錯誤地顯示'hostnamed' :-))。 –

+0

它仍然適用於主機名爲_的ogirinal解決方案:user @ host:/ netops/backups/scripts $ find/dir -type f -mtime -.9 -printf'%f \ n'| fgrep -eacs - eTFTP> fileb#我把這些文件放到fileb中 - 比如host22,hostx,hosty host22-crappyname-170803-0005.tar.gpg 2017-08-03-00-05-05_hostx_UCM_TFTP.tar 2017-08-03- 00-05-05_hosty_UCM_TFTP.tar用戶@主機:/ netops/backups/scripts $ cat $ mh hosta hsotb#不會將hostx或hosty與上面的_一起裝載到fileb中,因此它匹配並執行它的工作與文件2匹配_在其中。 –

相關問題