%2C%20%D1%83%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C%2F%D1%81%D0%BA%D1%80%D1%8B%D1%82%D1%8C%20%D0%B2%D1%81%D0%B5%20%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3%D0%B8.png)
Нуб здесь - я хочу бежать grep -r asdf
, однако,Мне нужны только уникальные совпадения в моих каталогах(т.е., игнорируя любой каталог, отображать только уникальные совпадения).
Итак, я запустил grep -r asdf | sort --unique
. Однако - это не работает, так как имена каталогов разные ( dir1/a.txt asdf
и dir2/a.txt asdf
).
Я не видел возможности (я пробовал, например grep -riol
) исключить каталоги, и я думаю, что это едва ли имеет смысл для области действия функции. Могу ли я как-то вырезать каталоги и показывать только совпавшее имя файла + совпадение (возможно, без регулярных выражений, ломающих разум/вселенную/sed/...)?
решение1
Я думаю, что с возможностями по умолчанию grep
это сделать никак не получится.
Вы можете использовать что-то вроде этого, что является просто «маленьким» регулярным выражением:
grep -r asdf | sed '#^.*/##' | sort --unique
Примечание: этот подход не будет работать, если шаблон поиска содержит/
решение2
Попробуй это,
grep -r abcd | awk -F ':' '{gsub(/.*\//,"",$1) }1' | awk '!seen[$1]++'
gsub
удалит структуру каталогов.(/.*\//,"",$1)
удалит("") все(.*) перед последним совпадением '/' в первом поле ($1).!seen[$1]++
сделает имя файла уникальным.
Примечание: в имени каталога не должно быть :
.
решение3
Это группирует по базовому имени и выводу grep:
]# grep -ro '#include' include/ |sed -E 's|.*/(.*:)|\1|' |uniq -c |sort|tail -n7
28 kvm_host.h:#include
28 mm.h:#include
29 ib_verbs.h:#include
31 net_namespace.h:#include
32 sock.h:#include
44 fs.h:#include
48 drmP.h:#include
Я раньше grep -o
получал дубликаты. В то же время он пропускал косые черты...
Если имена содержат :
sed не будет работать правильно. Регулярное выражение сначала отбрасывает все до последнего /
, затем сохраняет все до a :
как \1
.
Я использовал -E
из-за (подвыражения) и |
из-за слеша.
Подвыражение (.*:)
немного простое (выполнит ошибку, если строка grep содержит двоеточие). Если вы пропустите двоеточие, оно выполнит ошибку, если строка содержит косую черту.
Глядя на этот результат, я говорю:это невозможнов теории (чтобы проанализировать вывод grep таким образом):
]# grep -r "" d*
d:/ir:/afile...in file "d"
d:/ir:/afile...in file "ir"
Это идентично.Мне нужен был каталог с двоеточием в конце и файл с перекрывающимся именем и содержимым.
]# ls d*
d
'd:':
ir
grep --color
имеет значение!
Каталог include
— это тот, что из исходников ядра linux. Одна полная строка в одном include-файле выглядит так.
]# grep -rH '#incl' include/linux/aio.h
include/linux/aio.h:#include <linux/aio_abi.h>
решение4
При использовании выходных данных grep --null
следующая awk
программа GNU должна работать с любым именем файла:
BEGIN {
# OFS will be printed between
# each filename and matched line
OFS = ":"
# Use null-byte as a record separator
# to use with output from grep --null
RS = "\0"
# Apart from the first record,
# everything up to the first newline
# of a record is the matched line from grep
# Everything after first newline is a filename
FPAT = "^[^\n]*|\n.*$"
}
NR == 1 {
# Entire first record
# is the first filename
# set `file` to the basename
file = gensub(".*/","",1)
next
}
! seen[file, $1]++ {
# If filename+match
# not seen, print it
print file, $1
}
{
# Get basename of file
# from next match
file = gensub(".*/","",1,$2)
}
grep --null -rF asdf . | awk -f see_above.gawk