문맥
저는 우편 직원(메일 분류기)이고 정확한 거리 주소와 거리 이름의 처음 몇 글자를 입력하고 경로 번호 정보 문자열이 포함된 일치하는 문자를 반환하도록 하는 bash 스크립트를 작성하려고 합니다. . 나는 매일 편지를 살펴보고 도시의 모든 주소가 적힌 거대한 포스터를 살펴보며 처리할 수 없는 수천 통의 편지를 분류해야 했습니다. 이 스크립트를 사용하면 시간이 절약되므로 스크립트를 완료하는 과정을 배우기 위해 최선을 다하고 있습니다. 저는 UNIX/Linux 스크립팅에 대해 비슷한 취미를 가지고 있습니다. 여기서 정규 표현식이 해결책인지, 아니면 grep, find, awk, sed 또는 이들 모두의 변형인지 확실하지 않습니다!
주소 목록(집 번호 범위 및 거리 이름)이 포함된 텍스트 파일이 있는데, 각 주소는 다음과 같이 줄 바꿈되어 있습니다.
6974-7075 hwy 99: ss1
7757-8079 hwy 99: ss14
98-258 even foo st N: 15
97-257 odd foo st N: 16
21-301 foo st S: 17
15-20 foo st S: 7
bar st: 1
fake st: 31
fake pl: 77
sample dr: 89
번호 범위, 경로의 거리(집 번호는 제공되지 않음), 짝수 및 홀수 지정자, 도로 유형(st, hwy, pl, dr 등), 북쪽(N) 및 남쪽(S) 지정자가 있는지 확인하세요. 그리고 마지막으로 콜론 다음은 경로정보입니다.
현재 상태
텍스트 파일과 정확히 동일한 거리 번호를 입력하는 한 원하는 문자열을 반환하는 다음 스크립트가 있습니다.
#! /bin/bash
civic="$1"
street="$2"
grep $civic.*$street /path/to/addresses.txt
실행되었거나 ./script.sh 7757
나 에게 ./script.sh 7757 h
반환됩니다 . 7757-8079 hwy 99: ss14
콜론 뒤의 경로뿐만 아니라 전체 문자열이 여기에 반환된다는 점이 마음에 듭니다. 그러나 분명히 내 코드가 범위 내의 숫자를 확인하지 않았기 때문에 실행이 ./script.sh 8020 h
반환되지 않습니다 .7757-8079 hwy 99: ss14
도움이 필요하다
하지만 8020이 7757-8079 범위에 있으므로 8020 h
입력하고 계속 돌아올 수 있는 방법을 찾고 있습니다 .7757-8079 hwy 9: ss14
또한 foo st에는 N 및 S 표시기뿐만 아니라 다양한 경로에 대한 짝수 및 홀수 범위가 있다는 점을 텍스트에서 참고하세요. 집번호가 이상해서 돌아갈 필요 없이 들어가 107 f
거나 107 foo
돌아올 수 있는 방법을 찾고 있어요 . 이러한 짝수/홀수의 경우 단어 짝수/홀수는 항상 문자열에 지정되므로 입력 집 번호가 홀수이면 grep을 사용하거나 숫자 범위의 문자열에서 이러한 단어를 검색할 수 있습니까? 이 예 에서는 집 번호가 범위 내에 있고 문자열에 홀수가 있기 때문에 (foo st S 참고) 도 반환합니다 . N이나 S를 지정할 시간이 없기 때문에 N과 S를 반환하는 데 동의합니다.97-257 odd foo st N: 16
98-258 even foo st N: 15
21-301 odd foo st S: 17
완전한 답변이든, 더 자세한 힌트이든 제 노력에 도움을 주시면 매우 감사하겠습니다. 문제를 일으키려고 여기 온 것이 아니라 단지 도움을 요청하기 위한 것뿐입니다! 좀 더 구체적으로 설명할 수 있으면 알려주시기 바랍니다.
답변1
#! /bin/bash
civic="$1"
street="$2"
if [ "$((civic%2))" = 1 ]; then
exclude=" even "
else
exclude=" odd "
fi
</path/to/addresses.txt grep "$street" \
| grep -v "$exclude" \
| awk -F '[ -]' -v civic="$civic" '
{if ($1 !~ /^[0123456789]*$/ || $2 !~ /^[0123456789]*$/) print
else if (civic>=$1 && civic<=$2) print}
'
단계:
- 숫자가 홀수인지 짝수인지 확인하고 이에 따라 제외 문자열을 준비합니다.
- 첫 번째는
grep
거리와 일치하는 선을 선택합니다. 모든 행은 빈 문자열과 일치하므로 거리를 지정하지 않으면 이 단계에서 모든 행이 일치하게 됩니다. - 두 번째
grep
단계에서는 첫 번째 단계의 제외 문자열을 사용하여 "홀수" 또는 "짝수"로 설명된 항목을 제외합니다. awk
공백을 구분 기호로 사용하여 각 줄을 나눕니다-
. 처음 두 필드 중 하나가 정확히 숫자가 아닌 경우 범위가 지정되지 않고 행이 인쇄됩니다. 그렇지 않으면 분명히 처음 두 필드가 범위를 정의합니다. 그런 다음 숫자가 범위에 대해 테스트되고 범위 내에 있으면 줄이 인쇄됩니다.
답변2
포장지 awk
와 함께 제공됩니다 . bash
다른 이름으로 저장 script.sh
하고 실행 가능하게 만드세요.
#!/bin/bash
filename="data.txt"
n="$1" # save number from argument list
shift # remove number from argument list
s="$@" # save remaining argument list
s="${s:=.*}" # set regex .* as default if street is missing
awk -v number="$n" -v street="$s" '
BEGIN{
FS="-| " # use field separator "-" or one space to split current row
}
$0 ~ street{
# current row contains street
if( $1 ~ /^[0-9]+$/ && $2 ~ /^[0-9]+$/ ){
# current row starts with a range
if( number >= $1 && number <= $2 ){
# number is in expected range
if ( $3 == "odd" || $3 == "even" ){
# string "even" or "odd" found
if ( $3 == "odd" && number ~ /[13579]$/ ){
# odd
print
}
if ( $3 == "even" && number ~ /[24680]$/ ){
# even
print
}
} else {
# neither "even" or "odd" found
print
}
}
# finished with current row
next
}
# match but no range found in current row
print
}
' "$filename"