디렉터리 목록이 포함된 파일이 있습니다.
/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
필드 구분 기호를 로 설정한 /
다음 세 개의 필드만 포함하는 줄을 인쇄합니다. 입력 파일이 일관된 형식이라고 가정하면 다음 과 /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
피복재:
- 패턴 공간에는 항상 두 줄이 있는지 확인하세요.
- 첫 번째 부분이 패턴 공간의 두 번째 부분의 선행 위치에서 발견되지 않으면 => 동일한 분기에 속하지 않습니다. 첫 번째 부분을 인쇄하고 삭제한 다음 돌아가서 다음 줄을 패턴 공간으로 읽어 동일한 검사를 수행합니다.
- 일치하는 경우 두 번째 부분을 삭제하고, 이것이 더 큰 부분이므로(정렬된 입력 가정으로 인해) 해당 부분을 즉시 삭제합니다. 그런 다음 돌아가서 다음 줄을 패턴 공간으로 읽은 다음 헹구고 반복하십시오.
입력이 정렬되지 않은 경우 다음과 같이 수행할 수 있습니다.
$ 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의 모든 현재 키를 반복합니다.