awk
입력 파일의 행에 대해 요청한 내용에 따라 더하거나 뺄 수 있는 스크립트를 어떻게 작성할 수 있습니까 ? 나는 하나의 스크립트에서 덧셈이나 뺄셈만 수행하고 둘 중 하나는 수행하지 않는 방법을 알아냈습니다.
예를 들어 다음과 같은 입력을 원합니다.
ADD 5,10,20
SUB 30,5,20
다음 출력을 생성합니다.
35
-55
이것이 내가 지금까지 쓴 내용이다:
#!/bin/awk
BEGIN {
FS=","
}
{
for(i=1;i<=NF;i++)
sum+=$i;
print sum; sum=0}
하지만 분명히 덧셈만 할 뿐 모든 숫자를 얻지는 못하는 것 같습니다.
답변1
몇 가지 팁:
- 필드 구분 기호로 공백이나 쉼표를 사용합니다.
FS = "[ ,]"
- 그런 다음 당신이 했던 것처럼 숫자를 추가하세요.
i = 2
- 첫 번째 필드가 이면
SUB
합계에 -1을 곱합니다.
답변2
다음은 곱해진 값(1 또는 -1)을 유지하기 위해 연관 배열을 사용하여 Glenn Jackman의 알고리즘을 구현하는 한 가지 방법입니다.
$ awk -F ',|[[:blank:]]+' '
BEGIN {
mult["ADD"] = 1;
mult["SUB"] = -1;
};
$1 ~ /^(ADD|SUB)$/ {
sum = 0;
for (i=2; i <= NF; i++) { sum += $i };
print sum * mult[$1];
}' input.txt
35
-55
sum=$2
이는 또한 "MULT", "DIV" 또는 "EXP"( for 루프를 시작하는 대신 사용하는)와 같은 다른 키워드를 추가하기 위한 프레임워크의 시작을 제공합니다 .i=3
i=2
답변3
$ awk -F'[ ,]' '{sum=0; for (i=2; i<=NF; i++) sum+=$i; print ($1=="ADD" ? 1 : -1) * sum}' file
35
-55
예를 들어 ADD 및 SUB보다 더 많은 작업을 지원해야 하는 경우:
$ cat file
ADD 5,10,20
SUB 30,5,20
MULT 2,3,4
DIV 20,2,2
GNU awk를 사용하여 지원하려는 각 작업에 대한 함수를 정의하고 간접적으로 호출할 수 있습니다.
$ cat tst.awk
function ADD(n) { sum += n }
function SUB(n) { sum -= n }
function DIV(n) { if (n==0) { printf "%s[%d]: Divide by zero error in %s\n", FILENAME, FNR, $0 | "cat>&2"; exit 1 } sum /= n }
function MULT(n) { sum *= n }
BEGIN { FS="[ ,]" }
{
op = $1
sum = (op=="SUB" ? -1 : 1) * $2
for (i=3; i<=NF; i++) {
@op($i)
}
print sum
}
$ awk -f tst.awk file
35
-55
24
5
제공한 입력에서 원하는 출력을 얻으려면 특수한 경우 "SUB"를 사용해야 했습니다. 왜냐하면 나머지 입력과 다르게 처리되기 때문입니다(즉, 모든 숫자를 더하거나 곱셈/나눗셈을 더하는 대신 모든 숫자를 0에서 뺍니다). SUB 줄의 첫 번째 숫자가 -30
또는 0
이면 30
모든 작업을 정확히 동일한 방식으로 처리할 수 있습니다. 예를 들면 다음과 같습니다.
$ cat file
ADD 5,10,20
SUB 0,30,5,20
MULT 2,3,4
DIV 20,2,2
$ cat tst.awk
function ADD(n) { sum += n }
function SUB(n) { sum -= n }
function DIV(n) { if (n==0) { printf "%s[%d]: Divide by zero error in %s\n", FILENAME, FNR, $0 | "cat>&2"; exit 1 } sum /= n }
function MULT(n) { sum *= n }
BEGIN { FS="[ ,]" }
{
op = $1
sum = $2
for (i=3; i<=NF; i++) {
@op($i)
}
print sum
}
$ awk -f tst.awk file
35
-55
24
5