我有两个文件,我试图运行find / grep / fgrep。我一直在尝试几种不同的命令来尝试获得以下结果:
hostnamea
hostnameb
hostnamec
hostnamed
hostnamee
hostnamef
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
* about files- date = 20170802 - 大多数都有这种日期格式 - 有些日期格式不同*
FileA是我的控制文件 - 我想用整个单词hostnamea-f
搜索fileb并匹配fileb中的hostnamea-f
,并将filea
中的不匹配输出到终端上的输出在shell脚本中使用。
对于这个例子,我做了hostnamee
不在fileb中。我想运行一个fgrep / grep / awk - 无论什么都适用于此 - 并且只从filea输出缺少的hostnamee
。
我可以让它发挥作用,但它并没有特别做我需要的东西,如果我换掉它我什么也得不到。
user@host:/netops/backups/scripts$ fgrep -f filea fileb -i -w -o
hostnamea
hostnameb
hostnamec
hostnamed
HOSTNAMEF
很酷 - 我在File-B中获得了匹配但是如果我试图反转它会怎么样。
host@host:/netops/backups/scripts$ fgrep -f fileb filea -i -w -o
host@host:/netops/backups/scripts$
我尝试过几种不同的命令,但似乎无法正确使用。我使用-i忽略大小写,-w匹配整个单词和-o
我找到了某种解决方法,但希望有一种更优雅的方法,可以使用awk,egrep,fgrep或其他命令执行此操作。
user@host:/netops/backups/scripts$ fgrep -f filea fileb -i -w -o > test
user@host:/netops/backups/scripts$ diff filea test -i
5D4 < hostnamee
答案 0 :(得分:3)
你可以
-o
,a b -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的有趣输入,我已经将样本输入稍微变得更糟糕了#34;测试子字符串匹配和正则表达式活动字符的稳健性(例如"。"):
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"的部分内容,如果所有相邻的_
(以及其他"单词characers"始终被视为主机名的一部分。
(注意hostnamed
的附加输出行,现在在" b"中找不到了,因为在" b"中,它前面有一个_
。)
为了匹配可能出现的有效主机名,这些主机名前面/后面跟着其他单词字符,列表在" a"必须明确地命名这些变化。例如。 " _hostnamed"必须列出才能没有"主机名"在输出中。
(运气不错,这对于OP来说甚至可以接受,那么建议使用这个扩展解决方案;对于#Ed; EdMortonish陷阱的强健性" .Ed,请考虑这是对你有趣输入的赞美,这并不意味着无论如何都是消极的。)
" nasty"的输出a和b:
hostnamed
hostnamee
ostname
lilihostnamec
hos.namea
我不确定_
的更改处理是否仍然与OP目标相匹配(如果不是,在OP范围内,第一个不区分大小写的解决方案是否令人满意)。
_
是"字母字符的一部分"这可以用于"全字只匹配" -w
。更多详细的正则表达式控制在某些方面超出了grep,正如Ed Morton提到的那样,使用awk,perl(sed用于受虐狂的大脑锻炼,我喜欢的那种)是合适的。
在Windows上使用GNU grep 2.5.4。 文件a.txt和b.txt包含你的内容,但我确保它们有UNIX行结尾,这很重要(至少对于a,可能不是b)。
答案 1 :(得分: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()
即可使用适当的正则表达式。