다양한 명령에 대한 탭 완성을 자동으로 생성하려고 합니다. 다른 명령에 대한 매뉴얼 페이지를 awk로 옮긴 다음 -shortopt --long-option
각 명령을 별도의 줄에 인쇄하기 위해 명령줄 옵션(예: )을 검색했습니다.
for (i=1;i<NF;i++){
if(match("\<-[0-9a-zA-Z_-]\+\>", $i)){
print $i
}
}
어떤 이유로 이것은 작동하지 않습니다. 단일 백슬래시를 사용하는 경우 awk는 이스케이프 시퀀스가 무시되고 \<
리터럴로 처리된다는 경고를 표시합니다 \\<
. 두 개의 백슬래시를 사용하면 awk는 실제로 적절한 패턴과 일치하는 것을 거부합니다(vim에서 매뉴얼 페이지를 열고 패턴을 실행하면 작동하므로 패턴이 정확해야 한다고 가정합니다). 위의 코드 조각은 내가 호출하는 파일에 있으므로 man {section} {page} | awk -f find-options.awk
bash 및 awk에 의해 명령 문자열이 여러 번 구문 분석되는 문제를 배제할 수 있다고 생각합니다(예:백슬래시가 있는 awk FS) awk는 스크립트 파일을 직접 읽어야 하기 때문입니다.
답변1
man ls | col -bx | nawk '
{
for (ii=1;ii<=NF;ii++) {
if ( match($ii,/^(-[a-zA-Z0-9]|--[a-zA-Z0-9-]+)/) )
opt[substr($ii,RSTART,RLENGTH)]++
}
}
END { for (oo in opt) printf("%s\n",oo) } '
이는 "새로운" awk( nawk
, mawk
, gawk
)에서 작동합니다.
변경된 사항:
- 루프 변수 이름 합계 오류
match()
Ed Morton은 논쟁의 순서가 잘못되었음을 지적합니다.- 리터럴 정규식 의 경우
/.../
이스케이프하지 말고+
잘못된 사용법을 제거하십시오 ( "단어"가 아니고 문자, 숫자, 밑줄만 사용\<
하므로 일치하지 않습니다 ).-
- 파이프를 통해
col -b
백스페이스/오버슈트 제거 - 관찰된 모든 옵션을 배열에 저장하여 출력에서 중복을 억제합니다.
관찰된 이스케이프 오류는 match()
매개변수의 잘못된 순서로 인해 발생합니다. 리터럴 문자열의 "<"는 이스케이프할 필요도 없고 해서도 안 됩니다. 정규 표현식 에서만 특별한 의미를 가집니다 \<
(적절한 /.../
구분 기호 사용). 정규식이 리터럴 "문자열"이거나 변수에 있는 경우 정규식 표현에 "\\<"
리터럴 문자열을 사용할 수 있습니다.\<
이것배쉬 완료패키지에는 목표와 유사한 작업을 수행하는 함수가 있습니다. _longopt
이 함수는 명령을 호출하여 --help
동적으로 완성을 생성하고 궁극적으로 다음과 같은 것을 사용합니다.
compgen -W "$( LC_ALL=C $COMMAND --help 2>&1 | \
sed -ne 's/.*\(--[-A-Za-z0-9]\{1,\}=\{0,1\}\).*/\1/p' | sort -u )"
다음 구현을 찾을 수도 있습니다(perl).help2man
교육적으로 이는 "" 또는 이에 상응하는 출력을 처리하여 command --help
최소한의 매뉴얼 페이지를 생성합니다.
\<
¹그리고\>
너비가 0인 어설션POSIX가 아니며 현재는 흔하지 않으며 \b(?<=\W)
PCRE \b(?=\W)
에서 사용됩니다. gawk
이에 대한 기록은 없지만 GNUism을 지원 합니다. Solaris ERE 일치도 지원하지만 그렇지 awk
않습니다. 문자열의 시작이나 끝도 일치할 수 있으므로 예상대로 작동합니다(예: use /usr/xpg4/bin/grep -E
).
GNU awk에서 문자열의 시작/끝과 일치하지 않지만 다음 단어 문자와 일치 하도록 /-\<[0-9a-zA-Z_-]+\>/
변경되었습니다 .\<-
-\<