다음 형식의 데이터가 포함된 파일이 있습니다. 함께 있어야 하고 예측 가능한 패턴을 가져야 하는 3개의 행이 있습니다.
dn: uid=N-NAME-02, ou=data01, dc=data02, dc=data03
uidNumber: 3423
sambaSID: S-1-1-11-1111111-111111111-11111111-12342
<blank line>
dn: uid=N-NAME-03, ou=data01, dc=data02, dc=data03
uidNumber: 3245
sambaSID: S-1-1-11-1111111-111111111-11111111-32212
3개 그룹의 두 번째 데이터 문자열을 기반으로 몇 가지 수학을 수행한 다음 계산 결과를 해당 그룹의 세 번째 문자열에 입력해야 합니다.
dn: uid=NAME02, ou=data01, dc=data02, dc=data03
uidNumber: (3423 + 2 * 100)
sambaSID: S-1-1-11-1111111-111111111-11111111-342500
<blank line>
dn: uid=NAME03, ou=data01, dc=data02, dc=data03
uidNumber: (3245 + 2 * 100)
sambaSID: S-1-1-11-1111111-111111111-11111111-324700
AWK가 수학을 수행하고 결과 값을 올바르게 배치할 수 있기 때문에 이를 달성하기 위해 AWK를 다시 사용할 수 있다고 생각했습니다. 수학 부분을 직접 가져와서 변수에 저장했습니다.
variable1=`awk -F ': ' '/uidNumber:/ { new = $2 * 2 + 1000; print new }' infile`
그런 다음 동일한 파일의 다른 명령에서 이 변수를 사용하여 대체를 수행할 수 있습니다.
awk -F '-' -v variable2=$variable1 '/pattern of string 3 / { print $1"-"$2"-"$3"-"$4"-"$5"-"$6"-"$7"-"variable2 }'
문자열 3 데이터는 대시 "-"로 구분된 긴 문자열이라는 점을 언급해야 합니다. 마지막 대시 다음에는 계산된 값을 배치해야 합니다.
이것은 모두 작동하지만 한 가지 중요한 결함이 있습니다. 파일에 레코드가 하나 있는 경우에만 작동합니다. 누군가 나에게 이 작업을 수행하는 방법에 대한 힌트를 줄 수 있습니까?
답변1
match()
이 기능은 다음에서 사용할 수 있습니다 awk
.
$ cat file
somedata45
somedata47
somedata67
somedata53
somedata23
somedata12
awk '
BEGIN { RS = ""; OFS = "\n"; ORS = "\n\n" }
match($2, /[0-9]+/) { value = (substr($2, RSTART, RLENGTH) + 5) * 100 }
match($3, /[0-9]+/) { $3 = substr($2, 1, RSTART - 1) value }1' file
somedata45
somedata47
somedata5200
somedata53
somedata23
somedata2800
레코드 구분 기호를 공백으로 설정하여 단락 모드(빈 줄로 구분)를 효과적으로 활성화했습니다. 각 문단의 두 번째 줄은 우리의 것이 되고 $2
, 세 번째 줄은 $3 등이 됩니다. 출력 필드 구분 기호를 개행 문자로 설정했습니다. 단락 모드로 인해 출력 레코드 구분 기호도 두 개의 줄 바꿈으로 설정했습니다. 출력은 끝에 추가 줄 바꿈을 제공합니다.
우리는 이 match()
함수를 사용하여 숫자의 시작을 식별합니다. 일치 항목이 발견되면 함수는 두 개의 변수를 채우고 RSTART
일치 RLENGTH
항목이 시작된 시기와 지속 시간을 나타냅니다. 이러한 변수를 사용하여 계산을 수행하고 결과를 변수에 저장합니다 value
. 우리는 이 substr
기능을 사용하여 숫자를 찾습니다.
같은 일을 반복합니다 $3
. 이번에는 substr
숫자의 시작 부분을 인쇄하고 숫자 부분을 이전 줄에서 계산된 값을 포함하는 변수로 바꾸는 함수를 사용합니다.
참고하세요문자열 함수자세한 내용은 사용자 가이드를 참조하세요.
실제 데이터를 기반으로 업데이트되었습니다.
실제 데이터는 실제로 일을 훨씬 단순하게 만듭니다.
awk '
/^uidNumber/ { value = $NF }
/^sambaSID/ {
n = split ($NF, tmp, /-/)
tmp[n] = ((value + 2)* 100)
for (i=1; i<=n; i++) { nf = (nf ? nf "-" tmp[i] : tmp[i]) }
$NF = nf
nf = ""
}1' file
dn: uid=NAME02, ou=data01, dc=data02, dc=data03
uidNumber: 3423
sambaSID: S-1-1-11-1111111-111111111-11111111-342500
dn: uid=NAME03, ou=data01, dc=data02, dc=data03
uidNumber: 3245
sambaSID: S-1-1-11-1111111-111111111-11111111-324700
uidNumber
마지막 필드가 포함된 행을 찾아서 캡처합니다. 선이 보이면 sambaSID
마지막 필드를 분할 -
하고 마지막 요소를 새로 계산된 값으로 수정합니다. 그런 다음 for loop
a를 사용하여 마지막 필드를 다시 그룹화합니다.
답변2
awk 스크립트에서 이 작업을 수행하는 방법은 행 수를 계산하기 위해 일부 변수를 유지하는 것입니다. 단일 스크립트에서 이 작업을 수행할 수 있습니다.
/^[ \t]*$/ { lineCnt = 0; continue } # this matches blank lines and resets the count
{ lineCnt++ }
lineCnt == 2 { ... strip off your numeric ... }
lineCnt == 3 { ... do whatever you need to with the math ... }
라인 2와 3의 블록 끝에 "continue" 문을 추가하면 작업이 완료되었음을 알 수 있으므로 약간 더 효율적으로 만들 수 있습니다.
답변3
awk
서로의 변수 값을 사용하여 여러 패턴 동작 표현식을 결합하는 방법을 묻는 것 같습니다 . 예를 들어 매우 간단합니다.
awk '/pattern2/ { calculate and assign var }; /pattern3/ {do something with var}'
이 경우 ;
꼭 필요한 것은 아니지만 이해하는 데 도움이 됩니다. 한 줄 스크립트가 아닌 awk 스크립트에서는 표현식을 줄바꿈으로 구분할 수 있습니다.
예를 들어 file
다음과 같은 경우
pattern1
pattern2 3 5
pattern3
그 다음에
$ awk '/pattern2/ {var = $2+$3}; /pattern3/ {print; print var}' file
pattern3
8
또한 awk의 내장 함수 OFS
(출력 필드 구분 기호) 변수를 사용하면 출력 형식을 더 쉽게 지정할 수 있습니다.
pattern1
pattern2-3-5
pattern3-4-6
그 다음에
$ awk -F- '/pattern2/ {var = $2+$3}; /pattern3/ {OFS="-"; print $1,$2,$3,var}' file
pattern3-4-6-8