서비스 배포를 위한 Bash 스크립트가 있습니다. 서비스의 여러 인스턴스를 시작하는 데 사용되는 포트를 지정하려면 추가 명령줄 매개변수 형식으로 업데이트해야 합니다. 이 매개변수는 쉼표로 구분된 포트와 콜론으로 구분된 포트 범위를 허용합니다. 즉, 일부 유효한 값은 다음과 같습니다.
5001,5002,5003,5004
5001:5004
2003,4001:4008
1337,2300:2340,5000,5008
값을 배열로 읽어 범위를 확장해야 합니다(즉, 2003,4001:4008
값 배열의 경우와 동일해야 함 [2003,4001,4002,4003,4004,4005,4006,4007,4008]
).
Bash만 사용하여 이러한 모든 상황을 처리하는 효율적인 방법을 찾을 수 없는 것 같습니다(Perl에서는 허용하지 않지만 awk에서는 허용할 수 있습니다). 티아.
답변1
최신 awk
구현을 사용하십시오.
awk -v RS='[,\n]' -F: 'NF == 1; NF == 2 { for (i = $1; i <= $2; ++i) print i }'
위의 명령 awk
은 설명하는 형식으로 한 줄 또는 줄 집합을 읽고 각 쉼표 또는 개행으로 구분된 값을 "레코드"로 처리하고 각 콜론으로 구분된 문자열을 "필드"로 처리합니다.
레코드에 필드가 하나만 있는 경우( NF == 1
) 그대로 인쇄합니다. 입력에 포함된 범위가 아닌 값 중 하나입니다.
레코드에 두 개의 필드( NF == 2
)가 있는 경우 첫 번째 필드부터 두 번째 필드까지의 숫자를 인쇄합니다.
시험:
$ echo '2003,4001:4008' | awk -v RS='[,\n]' -F: 'NF == 1; NF == 2 { for (i = $1; i <= $2; ++i) print i }'
2003
4001
4002
4003
4004
4005
4006
4007
4008
그런 다음 생성된 목록을 원하는 방식으로 사용할 수 있습니다. 예를 들어,
#!/bin/sh
printf '%s\n' "$1" |
awk -v RS='[,\n]' -F: 'NF == 1; NF == 2 { for (i = $1; i <= $2; ++i) print i }' |
xargs -I {} some_executable ...options... --port={}
some_executable ...options... --port={}
이는 코드 의 각 숫자 출력에 대해 한 번씩 수행 되고 숫자로 대체됩니다 awk
. {}
이 awk
코드는 스크립트의 첫 번째 인수로 제공된 문자열을 가져옵니다.
제공된 매개변수에 대해서는 검증이 수행되지 않습니다.
답변2
데이터를 제어할 수 있으므로 매개변수와 중괄호 확장을 사용할 수 있습니다. 따옴표 없이 변수를 사용하여 eval
원하는 효과를 얻었 기 때문에 악의적인 입력을 방지하기 위해 Guard 절을 추가했습니다 .
expand() {
if [[ $1 == *[^,:[:digit:]]* ]]; then
echo "unexpected characters detected in argument" >&2
return 1
fi
local IFS=,
for val in $1; do
if [[ $val == *:* ]]; then
eval "printf '%s\n' {${val/:/..}}"
else
echo "$val"
fi
done
}
그런 다음 데이터로 테스트해 보세요.
while read line; do
readarray -t values < <(expand "$line")
declare -p values
done << 'END'
5001,5002,5003,5004
5001:5004
2003,4001:4008
1337,2300:2340,5000,5008
1,2,3,$(some malicious command),4
END
밝혀지다
declare -a values=([0]="5001" [1]="5002" [2]="5003" [3]="5004")
declare -a values=([0]="5001" [1]="5002" [2]="5003" [3]="5004")
declare -a values=([0]="2003" [1]="4001" [2]="4002" [3]="4003" [4]="4004" [5]="4005" [6]="4006" [7]="4007" [8]="4008")
declare -a values=([0]="1337" [1]="2300" [2]="2301" [3]="2302" [4]="2303" [5]="2304" [6]="2305" [7]="2306" [8]="2307" [9]="2308" [10]="2309" [11]="2310" [12]="2311" [13]="2312" [14]="2313" [15]="2314" [16]="2315" [17]="2316" [18]="2317" [19]="2318" [20]="2319" [21]="2320" [22]="2321" [23]="2322" [24]="2323" [25]="2324" [26]="2325" [27]="2326" [28]="2327" [29]="2328" [30]="2329" [31]="2330" [32]="2331" [33]="2332" [34]="2333" [35]="2334" [36]="2335" [37]="2336" [38]="2337" [39]="2338" [40]="2339" [41]="2340" [42]="5000" [43]="5008")
unexpected characters detected in argument
declare -a values=()
답변3
for j in `cat file`; do echo $j | perl -pne "s/,/\n/g"| awk -F ":" '/:/{for(i=$1;i<=$2;i++)print i}1'|sed '/:/d'| awk 'ORS=" "'; echo -e "\n";done
output
5001 5002 5003 5004
5001 5002 5003 5004
2003 4001 4002 4003 4004 4005 4006 4007 4008
1337 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323