FOR 루프에서 awk로 변수를 전달하여 특정 단어를 얻습니다.

FOR 루프에서 awk로 변수를 전달하여 특정 단어를 얻습니다.

테이블의 일부 단어를 CSV 형식의 TXT 파일로 인쇄하려고 합니다.

{...some code...}
number_lines=$(awk 'END { print NR }' Table1.txt
if [$number_lines -gt 5]
then
    for ((i=5; i<$number_lines; i++))
    do
       word=$(awk 'FNR==$i {print $2}' Table1.txt)
       echo $word
       printf "$variable1\t$variable2\t$variable3\t$word\n" >> Table2.csv
    done
fi

나는 i $2 행의 단어를 얻을 수 있다고 생각했고 FNR==5 {print $2} 를 사용하면 원하는 것을 얻을 수 있었지만 Table1.txt에 몇 개의 단어가 있는지 모르기 때문에 뭔가가 필요합니다. from 라인 5에서 시작하고(이전 라인은 필요하지 않기 때문에) Table1.txt의 라인 -1의 끝으로 이동합니다. 내 불쌍한 코드가 누군가를 화나게 하지 않기를 바랍니다. 나는 이 일을 급하게 해야 했고 이전에 bash에서 아무것도 한 적이 없었기 때문에 죄송합니다.

답변1

-v 옵션을 사용하여 쉘 변수를 awk 변수로 숨길 수 있습니다.

awk 명령은 다음과 같습니다:

awk -v Seq="$i" 'FNR==Seq {print $2}' Table1.txt

해당 수정 사항이 제안되면 10개 행을 모두 단일 awk 프로그램으로 바꾸는 것이 더 빠르고 더 깔끔할 것입니다. 이렇게 하면 Table1에 포함된 모든 행을 읽지 않아도 됩니다. awk는 행 계산과 데이터 읽기에 매우 능숙합니다.

테스트되지는 않았지만 "일부 코드" 뒤의 모든 내용을 다음으로 바꿉니다.

awk -v Vars="${variable1}\t${variable2}\t${variable3}\t" \
    'FNR >= 5 { printf ("%s\n%s%s\n", $2, Vars, $2); }' \
    Table1.txt > Table2.csv

답변2

awk전체 파일을 여러 번 읽고 처리하는 이와 같은 루프에서 반복적으로 실행하고 싶지는 않습니다 (라인 수 - 4회).

이상적으로는 모든 작업을 awk(또는 Perl 또는 쉘이 아닌 언어)로 수행하는 것이 더 나을 것입니다. 그러나 변수에 무엇이 있는지 또는 변수가 어떻게 정의되어 있는지 모르겠습니다 $variable[123](BTW, 아마도 bash에서 이를 수행하려면 다음을 사용해야 합니다). , 배열 사용) for 루프를 while 읽기 루프로 바꾸는 방법을 보여 드리겠습니다.

while read r word ; do
  echo "$word"
  printf "$variable1\t$variable2\t$variable3\t$word\n" >> Table2.csv
done < <(awk 'NR > 4 {print $2}')

아직은 별로네요(텍스트 처리를 위해 쉘 자체를 사용하는 것은 결코 좋은 생각이 아닙니다.), 그러나 적어도 awk한 번만 실행되고 입력 파일을 한 번만 읽습니다.

답변3

쉘 루프에서 반복적으로 awk를 호출하는 대신 awk를 한 번 호출하여 이 작업을 수행해야 합니다. 이는 매우 느리고 견고하게 코딩하기 어렵기 때문입니다. 간결하고 테스트 가능한 예제 입력 및 예상 출력을 게시하면 더 많은 도움을 드릴 수 있지만 아마도 다음과 같은 작업을 원하는 것 같습니다.

awk -v vars="$variable1\t$variable2\t$variable3" '
    BEGIN { OFS="\t" }
    NR>5 { print vars, prev }
    { prev = $2 }
' Table1.txt > Table2.csv

예를 들어:

$ variable1='this stuff'
$ variable2='other stuff'
$ variable3='last stuff'

$ cat Table1.txt
01      the     foo
02      quick   bar
03      brown   foo
04      fox     bar
05      jumped  foo
06      over    bar
07      the     foo
08      lazy    bar
09      dogs    foo
10      back    bar

$ awk -v vars="$variable1\t$variable2\t$variable3" '
    BEGIN { OFS="\t" }
    NR>5 { print vars, prev }
    { prev = $2 }
' Table1.txt > Table2.csv

$ cat Table2.csv
this stuff      other stuff     last stuff      jumped
this stuff      other stuff     last stuff      over
this stuff      other stuff     last stuff      the
this stuff      other stuff     last stuff      lazy
this stuff      other stuff     last stuff      dogs

$variable이러한 s 중 하나라도 확장하고 싶지 않은 이스케이프 시퀀스(예: 리터럴 탭 문자)를 포함할 수 있는 경우 \t다음을 수행하십시오.

vars="$variable1"$'\t'"$variable2"$'\t'"$variable3" awk '
    BEGIN { vars=ENVIRON["vars"]; OFS="\t" }
    NR>5 { print vars, prev }
    { prev = $2 }
' Table1.txt > Table2.csv

바라보다awk 스크립트에서 쉘 변수를 사용하는 방법쉘 변수의 값을 awk 스크립트에 전달하는 방법에 대한 추가 정보.

echo $word쉘 스크립트에서 이 문제를 해결하십시오. 이것이 디버그 인쇄라면 실제로는 stdout이 아닌 stderr로 이동해야 합니다(즉, 로 작성해야 함 echo "$word" >&2). 그러면 awk 스크립트는 다음과 같습니다.

$ awk -v vars="$variable1\t$variable2\t$variable3" '
    BEGIN { OFS="\t" }
    NR>5 {
        print prev | "cat>&2"   # or print prev > "/dev/stderr" if your awk supports that
        print vars, prev
    }
    { prev = $2 }
' Table1.txt > Table2.csv

그러나 정말로 표준 출력으로 내보내고 싶다면 다음과 같이 할 수 있습니다.

$ awk -v vars="$variable1\t$variable2\t$variable3" '
    BEGIN { OFS="\t" }
    NR>5 {
        print prev
        print vars, prev > "Table2.csv"
    }
    { prev = $2 }
' Table1.txt

또는:

$ awk -v vars="$variable1\t$variable2\t$variable3" '
    BEGIN { OFS="\t" }
    NR>5 {
        print prev
        print vars, prev | "cat>&3"
    }
    { prev = $2 }
' Table1.txt 3> "Table2.csv"

관련 정보