%E3%80%81%E3%81%99%E3%81%B9%E3%81%A6%E3%81%AE%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%82%92%E5%89%8A%E9%99%A4%2F%E9%9D%9E%E8%A1%A8%E7%A4%BA%E3%81%AB%E3%81%99%E3%82%8B.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 は正しく動作しません。正規表現は、まず最後の までのすべてを破棄し/
、次に までのすべてを として保存し:
ます\1
。
私は-E
(部分式) と|
スラッシュのために because を使用しました。
部分式(.*:)
は少し単純です (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 カーネル ソースからのものです。1 つのインクルード ファイル内の 1 行は次のようになります。
]# grep -rH '#incl' include/linux/aio.h
include/linux/aio.h:#include <linux/aio_abi.h>
答え4
からの出力ではgrep --null
、次の GNUawk
プログラムは任意のファイル名で動作するはずです。
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