ディレクトリのリストを含むファイルがあります。
/a/b
/a/b/c /a/b/
d /a/ b /
e
/a/c
/a/c/b
/a/c/d /
a/d/e /
a/d/e /f /a/e/f/g /a/e/ f /g
/
h
...
私は/a/b、/a/c、/a/d/e、および/a/e/f/gだけを取得したいと思います。つまり、他の行のサブセットが前にある行を除外したいということです。サブディレクトリの深さは任意であるため、2、3、4などに降りて、一意のサブディレクトリを見つけることができます。
答え1
入力がソートされたと仮定し、プレフィックスを確認して変更したら更新するのはどうですか?
$ awk 'NR == 1 || ! match($0, "^" pfx) {print; pfx = $0}' file
/a/b
/a/c
注:これは正規表現の一致であるため、アイテムに正規表現の特殊文字が含まれている場合は適切ではありません。 FWIWは、このコンテキストでは特殊文字として処理されないか、処理されないgawk
ようmawk
です。/
答え2
gawk -F/ '
{
# have we seen something that is a prefix of this line?
for (prefix in prefixes)
if ($0 ~ "^" prefix)
# yes we have
next
prefixes[$0] = 1
# are there prefixes that get "cancelled out" by this new one?
# e.g. /a/b/c is already a prefix but current line is /a/b
for (prefix in prefixes)
if (prefix ~ "^" $0 ".+")
delete prefixes[prefix]
}
END {
# GNU awk: traverse the array by index, sorted
PROCINFO["sorted_in"] = "@ind_str_asc"
for (p in prefixes)
print p
}
' list_of_dirs
出力
/a/b
/a/c
/a/d/e
/a/e/f/g
GNU awkがない場合は、出力を次にパイプします。| sort
答え3
$ awk -F/ 'NF==3 { print }' filename
フィールド区切り記号をに設定し、/
3つのフィールドのみを含む行を印刷します。入力ファイルが一貫した形式であると仮定すると、次/a/b
の行のみa
b
答え4
エディタを使用して、sed
次のようにこれを実行できます。
$ sed -e '
$!N
\|^\(.*\)\n\1/|!{P;D;}
s/\n.*//;H;s/.*//;x;D
' input_file
/a/b
/a/c
/a/d/e
/a/e/f/g
布材:
- パターンスペースには常に2行があることを確認してください。
- 最初の部分がパターン空間の2番目の部分の先行位置に見つからない場合、=>同じ分岐に属しません。最初の部分を印刷して削除し、戻って次の行をパターンスペースに読み込み、同じチェックを実行します。
- 一致する場合は、2番目の部分を削除し、これがより大きい部分であるため、並べ替えられた入力仮定のためにその部分をすぐに削除します。その後、戻って次の行をパターン空間に読み込み、すすぎ、繰り返します。
入力がソートされていない場合は、次のようにできます。
$ perl -lne '
my $l = $_;
grep !index($l,$_), keys %h or $h{$_}++;
}{print for sort keys %h;
' input
/a/b
/a/c
/a/d/e
/a/e/f/g
布材:
- index(str, substr) は、str で substr が見つかったインデックスを返します。最初から一致させるには、0を返し、成功として読み取るようにブール値を反転します。 grepは、キーが私たちが望む部分文字列であるハッシュ%hの現在のすべてのキーを繰り返します。