따라서 가능한 모든 상황을 올바르게 처리하는지 확인하기 위해 일부 기능에 대해 실행하고 싶은 테스트 명령으로 가득 찬 파일이 있습니다. 하지만 중복된 명령을 사용하는 것은 의미가 없습니다. 여기 몇 가지 예가 있어요.
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
'x'
대문자 앞에 소문자를 추가로 요구하려면 ASCII에서 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
하고 루프 후에 해당 변수에 대해 작업을 수행하면 중복 옵션에 대한 작업을 여러 번 방지할 수 있습니다.