
따라서 가능한 모든 상황을 올바르게 처리하는지 확인하기 위해 일부 기능에 대해 실행하고 싶은 테스트 명령으로 가득 찬 파일이 있습니다. 중복된 명령을 사용하는 것은 의미가 없습니다. 다음은 몇 가지 예입니다.
rap ,Xflg MIT X11
rap ,XPBfl 'MITER'
rap ,Bflg share git-grep
rap ,bfl X11
rap ,Bfl xzfgrep
rap ,Bf X11
... 내 기능 'rap'은 대시 대신 쉼표를 사용하여 문자 옵션의 시작을 나타내며 다음에는 몇 가지 인수가 있습니다. 이러한 옵션의 순서는 중요하지 않습니다.
rap ,Bf X11
rap ,fB X11
... 정확히 같은 명령입니다. 물론 파일에서 중복된 줄을 쉽게 제거할 수 있지만 위의 문제를 피하기 위해 내가 할 수 있는 일은 위의 내용이 끝나도록 옵션을 알파벳순으로 정렬하는 것입니다.
rap ,Bf X11
rap ,Bf X11
...그런 다음 중복 항목을 삭제할 수 있습니다. 영웅심 없이 그런 일을 할 수 있을까요? 이는 옵션 목록을 '기준'으로 정렬하는 것이 아니라 옵션 자체를 정렬하는 것입니다.
답변1
또 다른 perl
변형:
$ perl -pe 's{^rap ,\K\S+}{join "", sort split //, $&}e' file
rap ,Xfgl MIT X11
rap ,BPXfl 'MITER'
rap ,Bfgl share git-grep
rap ,bfl X11
rap ,Bfl xzfgrep
rap ,Bf X11
대문자 앞에 소문자를 추가로 요구하려면 ASCII에서 'x'
is 'X' ^ 32
(및 'X'
is 'x' ^ 32
)라는 사실을 사용할 수 있습니다.
$ perl -pe 's{^rap ,\K\S+}{join "", sort {(ord($a)^32) <=> (ord($b)^32)} split //, $&}e' file
rap ,fglX MIT X11
rap ,flBPX 'MITER'
rap ,fglB share git-grep
rap ,bfl X11
rap ,flB xzfgrep
rap ,fB X11
답변2
Perl을 사용하여 쉼표 뒤에 오는 일련의 단어 문자를 캡처하고 결과를 배열로 분할하고 정렬하고 결과를 대체할 수 있습니다.
$ perl -pe 's{(?<=,)(\w+)}{join "", sort split(//, $1)}e' yourfile
rap ,Xfgl MIT X11
rap ,BPXfl 'MITER'
rap ,Bfgl share git-grep
rap ,bfl X11
rap ,Bfl xzfgrep
rap ,Bf X11
요청에 따라 모든 대문자 옵션보다 먼저 모든 소문자 옵션을 정렬하는 한 가지(아마도 차선책) 방법이 있습니다.
$ perl -pe 's{(?<=,)(\w+)}{@opts = split(//,$1); join "",
(sort grep /[[:lower:]]/,@opts), (sort grep /[^[:lower:]]/, @opts)
}e' yourfile
rap ,fglX MIT X11
rap ,flBPX 'MITER'
rap ,fglB share git-grep
rap ,bfl X11
rap ,flB xzfgrep
rap ,fB X11
답변3
GNU awk 사용sorted_in
그리고 어쨌든 우리는 몇 가지 편리하지만 불필요한 확장인 gawk를 사용하고 있으므로 다음을 적용할 수 있습니다.장식-정렬-장식 취소 관용구1
소문자 문자 앞에 그리고 대문자 앞에 배치하여 2
소문자 문자를 대문자 앞에 모두 정렬한 다음 인쇄하기 전에 해당 장식을 다시 제거합니다.
$ cat tst.awk
BEGIN { PROCINFO["sorted_in"] = "@val_str_asc" }
match( $0, /^(\s*\S+\s*,)(\S+)(.*)/, a ) {
gsub( /[[:lower:]]/, "1 &,", a[2] ) # Decorate
gsub( /[[:upper:]]/, "2 &,", a[2] )
sorted = ""
split(a[2],opts,",")
for ( idx in opts ) { # Sort
sorted = sorted opts[idx]
}
gsub( /[[:digit:] ,]/, "", sorted ) # Undecorate
$0 = a[1] sorted a[3]
}
{ print }
$ awk -f tst.awk file
rap ,fglX MIT X11
rap ,flBPX 'MITER'
rap ,fglB share git-grep
rap ,bfl X11
rap ,flB xzfgrep
rap ,fB X11
답변4
입력 파일의 쉼표를 대시로 바꾸면 getopts
평소와 같이 함수의 옵션을 구문 분석 할 수 있습니다 rap
.
해당 변경은 으로 수행할 수 있으며, 줄의 시작 부분 sed
만 으로 변경해야 한다고 가정하면 다음과 같습니다.rap ,
rap -
sed 's/^rap ,/rap -/' file.in >file
그런 다음 함수가 이전에 선언되었다고 . ./file
가정하여 스크립트에서 생성된 파일을 간단히 소스로 제공할 수 있습니다 .rap
함수 의 옵션을 구문 분석하려면 다음을 수행하세요 rap
.
rap () {
OPTIND=1
unset -v B_flag P_flag X_flag
unset -v b_flag f_flag g_flag l_flag
while getopts BPXbfgl opt; do
case $opt in
B) B_flag=true ;;
P) P_flag=true ;;
X) X_flag=true ;;
b) b_flag=true ;;
f) f_flag=true ;;
g) g_flag=true ;;
l) l_flag=true ;;
*) echo 'Error' >&2; return 1
esac
done
shift "$(( OPTIND - 1 ))"
# Act on set flags here.
if "${f_flag-false}"; then
echo 'The -f option was used'
fi
# The non-options are available in "$@".
printf 'Other argument: %s\n' "$@"
printf -- '---\n'
}
루프 에서 플래그 변수를 설정 while
하고 루프 후에 해당 변수에 대해 작업을 수행하면 중복된 옵션에 대해 여러 번 작업하는 것을 방지할 수 있습니다.