이것이 나의 사명이다. 작업은 입력 파일에서 n개의 가장 긴 라인을 출력하는 것입니다. n에 매개변수가 없으면 n의 기본값은 5입니다. 인수에 파일이 없으면 표준 입력이 사용됩니다. 파일이 2개 이상인 경우 이름 파일을 출력합니다. 출력 라인의 순서는 원본 파일의 순서와 동일해야 합니다. 선택적 매개변수를 처리하기 위해 여기에 질문을 했습니다.쉘 스크립트에서 선택적 입력을 처리하는 방법은 무엇입니까?
그러나 새로운 쉘 스크립트에서 또 다른 문제가 발생했습니다.
#!/bin/sh
while getopts “n” arg; do
case $arg in
n)
# Check next positional parameter
eval nextopt=\${$OPTIND}
# existing or starting with dash?
if [[ -n $nextopt && $nextopt != -* ]] ; then
OPTIND=$((OPTIND + 1))
level=$nextopt
else
level=5
fi
;;
esac
done
for name do
if [ "$#" -gt 1 ]; then
printf 'File: %s\n' "$name"
fi
awk '{ print length(), NR, $0 | "sort -rn" }' $name | head -n $level | sed 's/[^ ]* //' | sort -n
done
저는 이렇게 운영해요
sh ex1.sh -n 10 unix1.txt unix1.1.txt
이것이 출력이다
File: -n
awk: can't open file -n
source line number 1
File: 10
awk: can't open file 10
source line number 1
File: unix1.txt
2 kbjkbkbbnbnmbnmnmmnbmnbmjbjkb
3 asjdsakdbakjsdbasbkj
4 asjdsakdbakjsdbasbkj
5 asjdsakdbakjsdbasbkj
10 ppûunsdj
11 tieutuvi
13 sdbhsdbjhdsvfdsvfgj
14 avavdvas
16 ffdsdfggdgdgdfgdfgdf112233
17 qwertyuiopsdfghjklxcvbnm,fghjk
File: unix1.1.txt
1 csdkbfsdk
2 fskjfnjkfnkjdsndjks
3 fsnjfnsjkf
4 snjfndsjknskjdfbnjksfdsfn
5 323124
6 jknjkkjnk4n4jn2
7 kjnjkb423
13 423b2j3kb4jk23bkb234kb32
14 234jb32jk43b
15 331
"-n"과 "10"은 파일이 아닙니다. 또 이렇게 달리면
sh ex1.sh -n unix1.txt unix1.1.txt
출력은 파일에서 가장 긴 5줄이어야 하지만 대신 다음과 같습니다.
File: -n
head: illegal line count -- unix1.txt
awk: can't open file -n
source line number 1
File: unix1.txt
head: illegal line count -- unix1.txt
File: unix1.1.txt
head: illegal line count -- unix1.txt
그렇다면 이 문제를 어떻게 해결해야 할까요? 이것이 목표는 아니지만 효과가 있을 것입니다.
while getopts “n” arg; do
case $arg in
n)
# Check next positional parameter
eval nextopt=\${$OPTIND}
# existing or starting with dash?
if [[ -n $nextopt && $nextopt != -* ]] ; then
OPTIND=$((OPTIND + 1))
level=$nextopt
else
level=5
fi
;;
esac
done
awk '{ print length(), NR, $0 | "sort -rn" }' unix1.txt | head -n $level | sed 's/[^ ]* //' | sort -n
내가 달리면
sh ex1.sh -n
나는 가지고있다
2 kbjkbkbbnbnmbnmnmmnbmnbmjbjkb
4 asjdsakdbakjsdbasbkj
5 asjdsakdbakjsdbasbkj
16 ffdsdfggdgdgdfgdfgdf112233
17 qwertyuiopsdfghjklxcvbnm,fghjk
또는
sh ex1.sh -n 10
나는 가지고있다
2 kbjkbkbbnbnmbnmnmmnbmnbmjbjkb
3 asjdsakdbakjsdbasbkj
4 asjdsakdbakjsdbasbkj
5 asjdsakdbakjsdbasbkj
10 ppûunsdj
11 tieutuvi
13 sdbhsdbjhdsvfdsvfgj
14 avavdvas
16 ffdsdfggdgdgdfgdfgdf112233
17 qwertyuiopsdfghjklxcvbnm,fghjk
어느 것이 정확합니까? 그리고, 매개변수에 파일이 없으면 표준입력을 사용하는데, 어떻게 처리하나요?
답변1
선택 -n
항목에 매개변수가 필요하므로 가 필요합니다 getopts 'n:' arg
.
옵션 매개변수는 에서 찾을 수 있습니다 $OPTARG
.
OPTIND
루프를 만지지 마십시오 while getopts
.
루프가 끝난 후 shift "$(( OPTIND - 1 ))"
.this는 위치 인수에 파일 이름을 유지합니다.
그건,
#!/bin/sh
level=5
while getopts 'n:' arg; do
case $arg in
n) level=$OPTARG ;;
*) echo 'Error in command line parsing' >&2
esac
done
shift "$(( OPTIND - 1 ))"
for name do
# stuff
done
다음으로 입력 파일이 없는 경우는 절대 처리하지 않습니다.
지정되지 않은 경우 다음 명령은 스크립트가 표준 입력을 파일 이름으로 사용하도록 합니다.
if [ "$#" -eq 0 ]; then
# handle no filenames, for example:
set -- /dev/stdin
fi
for name do
# stuff
done
나머지는 여러분에게 맡기겠습니다(하지만 명확성을 위해 파이프라인에서 자체 단계로 이동하고 실행하는 것이 좋습니다) sort
.awk
답변2
n에 매개변수가 없으면 n의 기본값은 5입니다.
getopt
not 을 사용하고 싶을 수도 있습니다 getopts
. bash 내장 기능이 아니므로 매뉴얼 페이지를 읽고 참조하십시오.샘플 코드
이 예제 스크립트가 주어지면
#!/usr/bin/env bash
tmp=$(getopt -o n:: --long n:: -- "$@")
if [[ $? -ne 0 ]]; then
echo "usage: ..." >&2
exit 1
fi
eval set -- "$tmp"
n=0
while :; do
case "$1" in
-n|--n) n=${2:-5}; shift 2 ;;
--) shift; break ;;
*) echo "error" >&2; exit 1 ;;
esac
done
echo "n = $n"
echo "remaining args:"
printf "%s\n" "$@"
이중 콜론은 옵션이 선택적 매개변수를 취함을 나타냅니다. 다양한 방법으로 호출되면 어떤 일이 발생하는지 확인하세요.
$ bash sample.sh foo bar
n = 0
remaining args:
foo
bar
$ bash sample.sh -n foo bar
n = 5
remaining args:
foo
bar
$ bash sample.sh -n 10 foo bar
n = 5
remaining args:
10
foo
bar
$ bash sample.sh -n10 foo bar
n = 10
remaining args:
foo
bar
$ bash sample.sh --n foo bar
n = 5
remaining args:
foo
bar
$ bash sample.sh --n 10 foo bar
n = 5
remaining args:
10
foo
bar
$ bash sample.sh --n=10 foo bar
n = 10
remaining args:
foo
bar
$ bash sample.sh --n= foo bar
n = 5
remaining args:
foo
bar
매뉴얼 페이지를 주의 깊게 읽으십시오:
간단한 짧은 옵션은 "
-
" 뒤에 짧은 옵션 문자가 오는 것입니다. 옵션에 필수 인수가 있는 경우 옵션 문자 바로 뒤에 쓰거나 다음 인수로 쓸 수 있습니다(예: 명령줄에서 공백으로 구분). 옵션에 선택적 인수가 있는 경우 옵션 문자(있는 경우) 바로 뒤에 작성해야 합니다..긴 옵션은 일반적
--
으로 " "로 시작하고 그 뒤에 긴 옵션 이름이 옵니다. 옵션에 필수 인수가 있는 경우 긴 옵션 이름 바로 뒤에=
" "로 구분하여 작성하거나 다음 인수로 작성할 수 있습니다(예: 명령줄에서 공백으로 구분). 옵션에 선택적 매개변수가 있는 경우 긴 옵션 이름 바로 뒤에=
' '로 구분하여 작성해야 합니다.존재하는 경우(=
뒤에 아무것도 없이 " "가 추가되면 인수가 없는 것처럼 해석됩니다. 이는 사소한 버그입니다. 버그를 참조하세요.)