๐ง AWK ๋ช ๋ น์ด ๋ฌธ๋ฒ ๋ง์คํฐ ๐ฏ ์ด์ ๋ฆฌ
AWK (Aho Weinberger Kernighan) ๊ฐ๋
AWK๋ ํ ์คํธ๊ฐ ์ ์ฅ๋์ด ์๋ ํ์ผ์ ์ํ๋ ๋๋ก ํํฐ๋งํ๊ฑฐ๋ ์ถ๊ฐํด์ฃผ๊ฑฐ๋ ๊ธฐํ ๊ฐ๊ณต์ ํตํด์ ๋์จ ๊ฒฐ๊ณผ๋ฅผ ํ๊ณผ ์ด๋ก ์ถ๋ ฅํด์ฃผ๋ ํ๋ก๊ทธ๋จ ์ด๋ค. ์ข๋ ์ฝ๊ฒ ๋งํ์๋ฉด, awk๋ "awk programming language"๋ผ๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ก ์์ฑ๋ ํ๋ก๊ทธ๋จ์ ์คํ ํ๋ ๋ช ๋ น์ด๋ผ๊ณ ์ดํดํ๋ฉด ์ข๋ค.
์ฆ, ๋ฆฌ๋ ์ค์์ ์ ์คํฌ๋ฆฝํธ(Shell Script)๋ก ์์ฑ๋ ํ์ผ์ด ๋ฆฌ๋ ์ค ์(Shell)์ ์ํด ์คํ๋๋ ๊ฒ์ฒ๋ผ, awk๊ฐ "awk programming language" ๋ฌธ๋ฒ์ผ๋ก ์์ฑ๋ ์ฝ๋๋ฅผ ์ดํดํ๊ณ ์คํ ํ๋ค๋ ์๋ฏธ๋ก ๋ณด๋ฉด ๋๋ค.
๋ช ๋ น์ด ์๋ฅผ ๋ค์๋ฉด, ๋ค์๊ณผ ๊ฐ์ด a.txt ํ์ผ์ด ์๋ค๊ณ ํ์. ํ์ผ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ๋ค.
1 2
3 4
๋ง์ผ 1์ด์ ๋ฐ์ดํฐ์ 2์ด์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ฐ ๊ณฑํ ๊ฐ์ ์ป๋ ๋ก์ง์ ( 1*2=2 / 3*4=12 ) awk ์ธ์ด๋ก ์์ฑ๋ awk๋ช ๋ น์ด๋ฅผ ํตํด ๊ตฌํํ๋ค๊ณ ํ๋ฉด
$ cat a.txt | awk '{print $1 * $2;}'
์ด๋ฐ์์ผ๋ก ๋ฐ๋ก ์์คํฌ๋ฆฝํธ ์์ฑ์์ด ๋จ ํ์ค๋ก ์คํฌ๋ฆฝํธ ๋์์ ๊ตฌํ ํ ์ ์๋ค.
awk๋ ํ์ผ๋ก๋ถํฐ ๋ ์ฝ๋(record)๋ฅผ ์ ํํ๊ณ , ์ ํ๋ ๋ ์ฝ๋์ ํฌํจ๋ ๊ฐ์ ์กฐ์ํ๊ฑฐ๋ ๋ฐ์ดํฐํ ํ๋ค.
์์ ๊ฐ์ ํ ์คํธ ํ์ผ ๋ด์ฉ์ด ์๋ค๋ฉด, ์ฌ๊ธฐ์ ๊ฐ ๋จ์ด๋ค์ ๊ณต๋ฐฑ์ผ๋ก ๊ตฌ๋ถ๋์ด์ ธ ์๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ๊ธฐ์ ๊ฐ ์ค(line)์ ๋ ์ฝ๋(Record)๋ผ๊ณ ์นญํ๊ณ ๊ทธ ์์ ๊ฐ๊ฐ์ ๋จ์ด๋ค์ด ํ๋(Field)๋ผ๊ณ ์นญํด์ง๋ค. (๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ ๊ณผ ๊ฐ๋ค.)
AWK ํ๋ก๊ทธ๋๋ฐ ๋ฌธ๋ฒ์์๋ ๋ ์ฝ๋๊ฐ $0, ๊ทธ๋ฆฌ๊ณ $1, ..., $N์ ๊ฐ ํ๋ ์ธ์๋ฅผ ๋ํ๋ด๊ฒ ํ๋ก๊ทธ๋๋ฐ ๋์ด ์๋ค.
๋ฐ๋ผ์, ์์์ ์์๋ฅผ ๋ ์ฝ๋๋ฅผ ๋ค์ ๋ณด์๋ฉด, ์ด๋ฐ์์ผ๋ก ํด์์ด ๋๋ค.
$0๋ ํ ํ์ ์๋ฏธํ๊ณ , $1 ๋ ๊ทธ ํ์ ์ฒซ๋ฒ์งธ ํ๋, $2 ๋ ๋๋ฒ์งธ ํ๋๊ฐ ๋๋ ๊ฒ์ด๋ค.
๊ฐ๋จํ๊ฒ awk๊ฐ ์ ๊ณตํด์ฃผ๋ ๋์ ์๋ฆฌ๋ฅผ ์ดํด๋ณด์๋ค.
์ ๋ฆฌํ์๋ฉด, awk๋ ๋ช ๋ น์ ์ ๋ ฅ์ผ๋ก ์ง์ ๋ ํ์ผ๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฅํ ๋ค์, ๋ถ๋ฅ๋ ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ์ผ๋ก ํจํด ๋งค์นญ ์ฌ๋ถ๋ฅผ ๊ฒ์ฌํ๊ฑฐ๋ ๋ฐ์ดํฐ ์กฐ์ ๋ฐ ์ฐ์ฐ ๋ฑ์ ์ก์ ์ ์ํํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ ๊ธฐ๋ฅ์ ์ํํ๋ ๊ฒ์ด๋ค.
๋ง์น ๋ฆฌ๋ ์ค์ SQL๋ฌธ์ด๋ผ๊ณ ์๊ฐํด๋ ๋๋ค.
ํ(๋ ์ฝ๋)๊ณผ ์ด(ํ๋)๋ก ์ด๋ฃจ์ด์ง ํ ์ด๋ธ ํํ์ FROM ๋ฐ์ดํฐ๋ค ์ค์์ ์ถ๋ ฅํ๊ณ ์ถ์ ์ด(ํ๋)๋ง SELECTํ๊ณ WHERE์ด๋ GROUP BY๋ฅผ ํตํด ๋ฐ์ดํฐ๋ค์ ํฉ์น๊ฑฐ๋ ์ผ๋ถ๋ง ๋ฝ์ ๋ด์ด ํ๋ฉด์ ์ถ๋ ฅํ๋ ๊ฒ์ด sql๋ฌธ์ธ๋ฐ, ์์ awk ๊ณผ์ ์ด ๋ฐ๋ก ์ด๊ฒ๊ณผ ๋ค๋ฆ์ด ์๊ธฐ ๋๋ฌธ์ด๋ค. ๊ฑฐ๊ธฐ๋ค SQL์ ์คํ ์ด๋ ํ๋ก์์ ๋ ํจ์์ฒ๋ผ awk์ญ์ ์กฐ๊ฑด๋ฌธ, ๋ฐ๋ณต๋ฌธ ์ฝ๋ฉ์ด ๊ฐ๋ฅํ๋ค.
awk ๋ช ๋ น์ผ๋ก ์ถ๋ ฅํ ์ ์๋ ์ผ๋ค์ ๊ฐ๋จํ ๋์ดํด ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค. ์ง๊ธ์ ์์ง ์ธ์ธํ ๋ฌธ๋ฒ์ ๋ชจ๋ฅด์ง๋ง ๋์ ์ตํ๋์.
AWK ๋ช ๋ น์ด ๋ฌธ๋ฒ
$ awk [์ต์
] 'pattern { action }' [ํ์ผ|๋ณ์๊ฐ]
awk ์ต์ | ์ค๋ช |
-u | ๋ฒํผ๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์ถ๋ ฅํ๋ค. |
-F | ํ์ฅ๋ ์ ๊ท ํํ์์ผ๋ก ํ๋๊ตฌ๋ถ์๋ฅผ ์ง์ ํ๋ค, ๋ค์ค ํ๋ ๊ตฌ๋ถ์ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค. |
awk -F | ๋จ์ผ๋ก ์ฌ์ฉ์ ':' ๋ฅผ ํ๋๊ตฌ๋ถ์๋ก ์ฌ์ฉ |
awk -F'[ :\t]' | ๋ค์ค ํ๋๊ตฌ๋ถ์ ':'์ tab์ ํ๋๊ตฌ๋ถ์๋ก ์ฌ์ฉ |
-v | ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๊ธฐ ์ ์ ๋ฏธ๋ฆฌ ๋ณ์๋ฅผ ์ง์ ํ์ฌ ์ค๋ค. |
-f | awk ๋ช ๋ น ์คํฌ๋ฆฝํธ๋ฅผ ํ์ผ์์ ์ฝ์ด์จ๋ค. |
awk ๋์ ์๋ฆฌ
ํจํด(pattern) ๊ณผ ์ก์ (action)
- awk๋ ํ์ผ ๋๋ ํ์ดํ๋ฅผ ํตํด ์
๋ ฅ ๋ผ์ธ์ ์ป์ด์ $0๋ผ๋ ๋ด๋ถ ๋ณ์์ ๋ผ์ธ์ ์
๋ ฅํ๋ค.
๊ฐ ๋ผ์ธ์ ๋ ์ฝ๋๋ผ๊ณ ๋ถ๋ฅด๊ณ , newline(๊ฐํ)์ ์ํด ๊ตฌ๋ถ๋๋ค.
์ด๋ ํจํด์ด ์์ผ๋ฉด ์ ์ฒด ๋ผ์ธ์ ์ป์ด์ค๊ณ , ์ํ๋ ๋ผ์ธ๋ง ์ป์ด์ค๊ณ ์ถ์๋๋ ํจํด์ ์ฌ์ฉํด ๋ถ๋ณํ ์ ์๋ค. - awk๋ฅผ ์คํํ ๋ ๋ด์ฅ ๋ณ์์ธ FS๋ผ๊ณ ๋ถ๋ฅด๋ ํ๋ ๋ถ๋ฆฌ์๊ฐ ๊ณต๋ฐฑ์ ํ ๋น ๋ฐ๋๋ค. (ํ๋ ๋ถ๋ฆฌ ๊ธฐ์ค์ ๊ณต๋ฐฑ์ด ์๋ ๋ค๋ฅธ ๊ฐ์ผ๋ก ๋ฐ๊ฟ์๋ ์๋ค)
๊ทธ๋ฌ๋ฉด awk๋ ๋ผ์ธ์ ๊ณต๋ฐฑ์ ๊ธฐ์ค์ผ๋ก ๊ฐ๊ฐ์ ํ๋๋ ๋จ์ด๋ก ๋๋๋ค.
ํ๋๋ $1๋ถํฐ ์์ํด์ ๋ง๊ฒ๋ $100 ์ด์์ ๋ณ์์ ์ ์ฅํ ์ ์๋ค. - ๊ฐ ํ๋ ๋ฐ์ดํฐ๋ค์ ์ ์ฅํ๋ค๋ฉด awk๋ ์ก์
์ ํตํด ๋์ ์คํฌ๋ฆฝํ
์ ํ ์ ์๋ค.
์๋ฅผ ๋ค์ด, ํ๋๋ค์ ํ๋ฉด์ ์ถ๋ ฅํ ๋ print ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
# -F : ํ๋ ๊ตฌ๋ถ ๋ฌธ์๋ฅผ ๊ณต๋ฐฑ ๋ง๊ณ ":" ๋ก ์ค์
# pattern /linux/ : linux ๋ฌธ์์ด์ ํฌํจํ ๋ชจ๋ ๋ ์ฝ๋ ์ถ๋ ฅ
# action {print $1} : ๊ฐ ํ(๋ ์ฝ๋)์์ ์ฒซ๋ฒ์งธ ํ๋๋ฅผ ์ถ๋ ฅ
$ awk -F":" '/linux/ {print $1}' test.txxt
pattern ๊ณผ { action }์ ๋ฐ๋์ ๋ช ๋ น์ด์ ๋ชจ๋ ์จ์ค์ผ ๋๋ ๊ฑด ์๋๋ค.
์๋์ ๊ฐ์ด pattern์ด ์๋ต๋๋ ๊ฒฝ์ฐ,
๋งค์นญ ์ฌ๋ถ๋ฅผ ๊ฒ์ฌํ ๋ฌธ์์ด ํจํด ์ ๋ณด๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ๋ ์ฝ๋๊ฐ ์ ํ๋๋ ๊ฑฐ๊ณ ,
# pattern ์๋ต.
$ awk '{ print }' ./file.txt # file.txt์ ๋ชจ๋ ๋ ์ฝ๋ ์ถ๋ ฅ.
action์ ์๋ตํ๋ฉด, ๊ธฐ๋ณธ ์ก์ ์ธ print๊ฐ ์คํ๋๋ค.
# action ์๋ต.
$ awk '/p/' ./file.txt # file.txt์์ p๋ฅผ ํฌํจํ๋ ๋ ์ฝ๋ ์ถ๋ ฅ.
awk ๋ช ๋ น์ด๋ ๋จ์ผ๋ก file์ ์ฐธ์กฐํด์ ์คํํด๋ ๋๊ณ ,
๋ค๋ฅธ ๋ช ๋ น์ด์ ํ์ดํ์ ์กฐํฉํ์ฌ๋ ์ฌ์ฉํ ์ ์๋ค.
# ํ์ผ์์ ์
๋ ฅ์ ๋ฐ์๋ค์ผ ๋ #
$ awk 'pattern' filename
$ awk '{ action }' filename
$ awk 'pattern { action }' filename
# ์ปค๋งจ๋์์ ์
๋ ฅ์ ๋ฐ์๋ค ๋ ํ์ดํ์ ์กฐํฉํ์ฌ ์ฌ์ฉ #
$ command | awk 'pattern'
$ command | awk '{ action }'
$ command | awk 'pattern { action }'
awk ํจํด ์ข ๋ฅ
๋น๊ต์ฐ์ฐ ํจํด
๋ค์ ์ ๋ฆฌํ์๋ฉด, ํจํด์ ๊ฐ ๋ผ์ธ(ํ) ๋ค ์ค์, ๋ด๊ฐ ์ํ๋ ๋ถ๋ถ๋ง ๋ฝ์๋ด๊ณ ์ถ์๋ ์ฌ์ฉํ๋ค.
๊ฐ์ฅ ๊ฐ๋จํ๊ฒ ์ฌ์ฉํ ์ ์๋๊ฒ ๋น๊ต ์ฐ์ฐ ํจํด์ธ๋ฐ, ๋ง์น ์กฐ๊ฑด๋ฌธ ์ฒ๋ผ ํด๋น ์กฐ๊ฑด์ ๋ถํฉํ ๋ฐ์ดํฐ ๋ผ์ธ๋ค์ ๋ฝ์ ๋ธ๋ค.
์ซ์, ์ํ๋ฒณ ๋ชจ๋ ๋น๊ต ์ฐ์ฐ์ด ๊ฐ๋ฅ ํ๋ค.
# ํ์ผ์์ 3๋ฒ์งธ ํ๋ $3์ ๊ฐ์ด 7000๋ณด๋ค ํด๊ฒฝ์ฐ ๋๋จธ์ง ํ๋๋ค์ printํ๋ค.
$ awk '$3 > 7000 {print $1, $2}' filename
# ๋ณต์กํ ๋
ผ๋ฆฌ์ ์ฌ๊น ์ฌ์ฉ ๊ฐ๋ฅ
$ awk '$3 > $5 && $3 <= 100' filename
์ ๊ทํํ์ ํจํด
grep ๋ช ๋ น์ด์ ๊ฐ์ด ํจํด ๋ถ๋ถ์ ์ ๊ท์ /regex/ ๋ฅผ ๋ฃ์ด์ ๋ผ์ธ์ ๋ถ๋ณ ํ ์๋ ์๋ค.
# ๋์๋ฌธ์ ๊ตฌ๋ถ์๋ ์ํ๋ฒณ์ผ๋ก ์์ํ๊ณ ๋ค์ ์ด๋ ํ ๋ฌธ์๊ฐ ์ค๋ ๋ผ์ธ ๋งค์นญ
$ awk '/^[A-Z][a-z]+ /' filename
# "์ " ์๋ก ์์ํ๋ ๋ผ์ธ์ ๊ณจ๋ผ์ print
$ awk '/^์ /{print $1, $2, $3}' filename
# POSIX ๋ฌธ์ ํด๋์ค
$ awk '/[[:lower:]]+g[[:space:]]+[[:digit:]]' filename
์ ๊ท์๊ณผ POSIX ๊ฐ ๋ฌด์์ธ์ง ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด, ํด๋น ํฌ์คํ ์ ์ฐธ๊ณ ํ๊ธธ ๋ฐ๋๋ค.
[LINUX] ๐ ์ ๊ทํํ์ ๊ณผ grep ๋ช ๋ น์ด ์ ๋ณตํ๊ธฐ [ํจํด ๊ฒ์] [ํ์ฅ๋ธ๋ํท]
ํ์ผ/๋๋ ํ ๋ฆฌ ํจํด ๊ฒ์ ๋ฆฌ๋ ์ค๋ฅผ ์ฌ์ฉํ๋ค ๋ณด๋ฉด ๋ก๊ทธํ์ผ์ด๋, ํ ์คํธ ํ์ผ์์ ํน์ ๋ฌธ์์ด์ ์ฐพ์ ๋, ํน์ ๋๋ ํฐ๋ฆฌ ๋ด์์ ํน์ ๋ฌธ์๋ฅผ ํฌํจํ๋ ํ์ผ์ ์ฐพ์ ๋์ ๊ฐ์ ๊ฒฝ์ฐ๊ฐ ์๊ธด๋ค.
inpa.tistory.com
ํจํด ๋งค์นญ ์ฐ์ฐ
match ์ฐ์ฐ์(~) : ํํ์๊ณผ ๋งค์นญ๋๋ ๊ฒ์ด ์๋์ง ๊ฒ์ฌํ๋ ์ฐ์ฐ์
- ~ ์ผ์นํ๋ ๋ถ๋ถ
- !~ ์ผ์นํ์ง ์๋ ๋ถ๋ถ
์๋ก์ด ๋ฌธ๋ฒ์ด์ง๋ง, ์ด๋ ๊ฒ ์ดํดํ๋ฉด ๊ฐ๋จํ๋ค. ๋ณดํต ๊ฐ์ ๋น๊ตํ ๋, == ์ฐ์ฐ์๋ฅผ ์ฐ๋๋ฐ, ํจํด๋งค์นญ์ ๋น๊ตํ๊ธฐ ์ํด์ == ๋์ match์ฐ์ฐ์(~)๋ฅผ ์ฐ๋ ๊ฒ์ด๋ค.
# 2๋ฒ ํ๋ ๋ฌธ์์ด์ด ๋ฌธ์ g๋ก ๋๋์ง ์๋ ๋ผ์ธ ์ถ๋ ฅ
$ awk '$2 !~ /g$/' filename
BEGIN / END ํจํด
awk ํจํด(pattern) ์ค์๋ "BEGIN" ๊ณผ "END" ๋ผ๊ณ ํ๋ ํน๋ณํ ํจํด์ด ์กด์ฌํ๋ค.
awk๊ฐ BEGIN ํจํด์ ์๋ณํ๋ฉด ์ ๋ ฅ ๋ฐ์ดํฐ๋ก๋ถํฐ ์ฒซ ๋ฒ์งธ ๋ ์ฝ๋๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ ์ "BEGIN"์ ์ง์ ๋ ์ก์ ์ ์คํํ๋ค. ๊ทธ๋ฆฌ๊ณ "END" ํจํด์ ๋ชจ๋ ๋ ์ฝ๋๋ฅผ ์ฒ๋ฆฌํ ๋ค์ "END"์ ์ง์ ๋ ์ก์ ์ ์คํํ๋ ์๋ฆฌ์ด๋ค.
์ ๋ง ์๊ธฐ์ฝ๊ฒ ์์ ๋ก ๊ทธ๋ฆผ์ผ๋ก ํํํ์๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
[file.txt ํ์ผ ๋ด์ฉ]
1 2
3 4
5 6
7 8
$ awk 'BEGIN { print "TITLE : Field value 1,2"} {print $1, $2} END {print "Finished"}' file.txt
awk ์ ์ด๋ฌธ
๋ฌธ๋ฒ ์์ฒด๋ C์ธ์ด์ ์ ์ด๋ฌธ๊ณผ ๋น์ทํ๋ค.
# if๋ฌธ
if ( condition ) { Routine } else { Routine }
# for๋ฌธ
for ( init ; condition ; re ) { Routine }
# while๋ฌธ
while (condition) { Routine }
# do ~ while๋ฌธ
do { Routine } while (condition)
# ๋ฐ๋ชฉ๋ฌธ ์ ์ด
break
continue
return
# ํ๋ก๊ทธ๋จ ์ ์ด
next
exit
if๋ฌธ
# ๋จ์ผ if
$ awk '{if($6>50) print $1 "Too high" }' filename
$ awk '{if($6>20 && $6<=50) {safe++; print "OK"}}' filename
# if ~ else
$ awk '{if($6>50) print $1 "Too high"; else print "Range is OK"}' filename
$ awk '{if($6>50) {count++; print $3} else{x+5; print $2}}' filename
ํ์ค๋ก ํํํ๋ค๋ณด๋ ๊ต์ฅํ ๊ฐ๋ ์ฑ์ด ์์ข๋ค.
๋คํํ awk๋ ๊ฐํ ๋ฌธ๋ฒ์ ์ง์ํ๋ค.
๋ค์๊ณผ ๊ฐ์ ํ์ผ๋ด์ฉ์ด ์๋ค๊ณ ํ์.
๊ฐ ๋ผ์ธ์์ ์ฒซ๋ฒ์งธ ํ๋ $1๊ฐ "d" ๋ก ์์ํ๋ฉด, ์ฆ ๋๋ ํ ๋ฆฌ๋ผ๋ฉด ์ถ๋ ฅํ๊ณ ์๋๋ฉด null๋ฅผ ์ถ๋ ฅํ๋ ๊ฐ๋จํ if๋ฌธ ์์ ์ด๋ค.
$ awk '{
if ($3 >=35 && $4 >= 35 && $5 >= 35)
print $0,"=>","Pass";
else
print $0,"=>","Fail";
}' filename
$ awk \ # \๋ฌธ์๋ฅผ ์จ๋ ํฐ๋ฏธ๋์์ ๊ฐํ์ด ๊ฐ๋ฅํ๋ค.
'
{
if ($3 >=35 && $4 >= 35 && $5 >= 35)
print $0,"=>","Pass";
else
print $0,"=>","Fail";
}
'
# if elif else
$ awk '{
total=$3+$4+$5;
avg=total/3;
if ( avg >= 90 )
grade="A";
else if ( avg >= 80)
grade ="B";
else if (avg >= 70)
grade ="C";
else
grade="D";
print $0, grade;
}' filename
# ์ผํญ ์ฐ์ฐ์ ์ญ์ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค
$ awk '{max={$1 > $2) ? $1 : $2; print max}' filename
for๋ฌธ
$ awk '{for(i=1; i<=NF; i++) print NF, $1}' filename
$ awk '{
for(i=0;i<2;i++)
print( "for loop :" i "\t" $1, $2, $3)
}' filename
while๋ฌธ
$ awk '{i=1; while(i<=NF) {print NF, $1; i++}}' filename
๋ฐ๋ณต๋ฌธ ์ ์ด
- break : ์กฐ๊ฑด์ ๋ง์กฑํ๋ฉด ๋ฐ๋ณต๋ฌธ์ ํ์ถ
- continue : ๋จ์์๋ ๋ฌธ์ฅ์ ์คํํ์ง ์๊ณ , ๋ฐ๋ก ๋ฐ๋ณต๋ฌธ์ ์์ ๋ถ๋ถ์ผ๋ก ์ ์ด๋ฅผ ์ด๋
$ awk '{
for(x=3; x<=NF; x++)
if($x<0) {print "Bottomed out!"; break}
for(x=3; x<=NF; x++)
if($x==0) {print "Get next item"; continue}
}' filename
ํ๋ก๊ทธ๋จ ์ ์ด
- next : ์ ๋ ฅ ํ์ผ๋ก๋ถํฐ ๋ค์ ์ ๋ ฅํ์ ๊ฐ์ ธ์์ awk ์คํฌ๋ฆฝํธ์ ๋งจ ์ฒ์๋ถํฐ ๋ค์ ์คํ
- exit : awk ํ๋ก๊ทธ๋จ์ ์ข ๋ฃ์ํฌ ๋ ์ฌ์ฉ. exit ๋ฌธ์ ๋ ์ฝ๋์ ์ฒ๋ฆฌ๋ฅผ ์ค๋จ์ํค์ง๋ง, END ๋ฌธ ๋๋จธ๋ก ๊ฑด๋๋ฐ์ง ์์
# 1๋ฒ์งธ ํ๋๊ฐ Peter๋ฅผ ํฌํจํ๋ฉด ์ด ํ์ ์ง๋๊ณ ๋ค์ํ์ ์
๋ ฅ๋ฐ๊ณ , ์คํฌ๋ฆฝํธ๋ ์ฒ์๋ถํฐ ๋ค์ ์คํ
$ awk '{
if($1~/Peter/) {next}
else {print}
}' filename
$ cat file.txt
1 ppotta 30 40 50
2 soft 60 70 80
3 prog 90 10 20
$ awk '{ print $0; exit }' file.txt # ์ฒซ ๋ฒ์งธ ๋ ์ฝ๋๋ง ์ถ๋ ฅํ๊ณ ์คํ ์ค์ง.
1 ppotta 30 40 50
$ awk 'NR == 2 { print $0; exit }' file.txt # ๋ ๋ฒ์งธ ๋ ์ฝ๋๋ง ์ถ๋ ฅํ๊ณ ์คํ ์ค์ง.
2 soft 60 70 80
NR์ ์ถ๋ ฅ ์๋ฒ์ ๋ํ๋ด๋ awk ์ ์ฉ ๋ด์ฅ๋ณ์์ด๋ค.
awk ์ฌ์ฉ์ ๋ณ์
์ฌํ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ๊ฐ์ด ๋ณ์๋ฅผ ๋ง๋ค์ด์ ์ฌ์ฉํ ์ ์๋ค.
$ awk '
BEGIN {
sum = 0
cnt = -1
}
{
sum += $5
cnt++
}
END {
avg = sum/cnt
print ("sum :" sum ", average :" avg)
}' filename
awk ๋ฆฌ๋ค์ด๋ ์
awk๊ฒฐ๊ณผ๋ฅผ ๋ฆฌ๋ ์ค ํ์ผ๋ก ๋ฆฌ๋ค์ด๋ ์ ํ ๊ฒฝ์ฐ ์ ๋ฆฌ๋ค์ด๋ ์ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋ค.
๋ค๋ง > ๊ธฐํธ๊ฐ ๋ ผ๋ฆฌ์ฐ์ฐ์์ธ์ง ๋ฆฌ๋ค์ด๋ ์ ์ธ์ง ๋ชจํธํ ๋๊ฐ ์๋๋ฐ, ๊ทธ๋ฅ action ๋ถ๋ถ์ > ๊ธฐํธ๊ฐ ์ฐ์ด๋ฉด ๋ฆฌ๋ค์ด๋ ์ , pattern ๋ถ๋ถ์ ์ฐ์ด๋ฉด ๋ ผ๋ฆฌ ์ฐ์ฐ์ด๋ผ๊ณ ์น๋ถํ๋ฉด ๋๋ค.
ํ์ผ๋ช ์ ํฐ๋ฐ์ดํ๋ก ๋๋ฌ์ฐ์ ์ธ์ ๋๋ค.
$ awk -F: '$4 >= 60000 {print $1, $2 > "new_file"}' awkfile5
.awk ํ์ผ๋ก ๋ง๋ค์ด์ ์คํ
์ ์คํฌ๋ฆฝํธ๋ฅผ .sh ํ์ผ๋ก ๋ง๋ค์ด์ ์คํํ ์ ์๋ฏ์ด, awk์ญ์ ๊ฐ๋ฅํ๋ค. -f ๋ช ๋ น์ด ์ต์ ์ ์ฌ์ฉํ๋ฉด .awk ํ์ฅ์ ํ์ผ์ ์คํ ํ ์ ์๋ค.
๋ฌธ๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค. ์์คํฌ๋ฆฝํธ์์ #!/bin/bash์ ๊ฐ์ด awk ์ ์ฉ shabang์ ์์ฑํด์ฃผ๊ณ , ์ง๊ธ๊น์ง ๋ฐฐ์ด ๋ฌธ๋ฒ์ ๊ทธ๋๋ก ์ ์ด์ฃผ๊ธฐ๋ฉด ํ๋ฉด ๋๋ค. (๋จ, ์ฐธ์กฐํ ํ์ผ์ ์ ์ง ์๋๋ค. ํ์ผ์ ํฐ๋ฏธ๋ CLI๋ช ๋ น์ผ๋ก ์ ๋๋ค)
#!/bin/awk -f
BEGIN { print "File\tOwner" }
{ print $8, "\t", $3}
END { print " - DONE -" }
# ์คํ๋ฐฉ์ : awk [-f์ต์
] [awk์คํฌ๋ฆฝํธํ์ผ] [์ฐธ์กฐํ ํ์ผ]
$ awk -f script.awk filename
awk ์ฐ์ฐ์
์ฐ์ฐ์ | ์ค๋ช |
์ฐ ์ | =, +=, -=, *=, /=, %= |
์กฐ ๊ฑด | ?, : |
๋ ผ ๋ฆฌ | ||, &&, ! |
ํจ ํด | ~, !~ |
๋น ๊ต | <, <=, >, >=, !=, == |
์ฆ ๊ฐ | ++, -- |
ํ๋์ฐธ์กฐ | $ |
awk ๋ด์ฅ๋ณ์
ํค์๋ | ์ค๋ช |
FILENAME | ํ์ฌ ์ ๋ ฅํ์ผ์ ์ด๋ฆ |
$0 | ์ ๋ ฅ ๋ ์ฝ๋ |
$n | ์ ๋ ฅ ๋ ์ฝ๋์ N๋ฒ์งธ ํ๋ |
ENVIRON | ํ๊ฒฝ๋ณ์๋ฅผ ๋ชจ์๋ ๊ด๊ณํ ๋ฐฐ์ด |
NR | ์ถ๋ ฅ ์๋ฒ |
NF | ํ์ฌ ์ค์ ํ๋์ |
ARGC | ๋ช ๋ น์ค ์ธ์์ ๊ฐ์ |
ARGV | ๋ช ๋ น์ค ์ธ์๋ค์ ๋ฐฐ์ด |
FNR | ํ์ฌํ์ผ์์์ ๋ ์ฝ๋ ๋ฒํธ |
FS | ์ ๋ ฅ ํ๋ ๊ตฌ๋ถ์ |
OFMT | ์ซ์๋ค์ ํํํ์ |
OFS | ์ถ๋ ฅํ๋ ๊ตฌ๋ถ์ |
ORS | ์ถ๋ ฅ ๋ ์ฝ๋ ๊ตฌ๋ถ์ |
RS | ์ ๋ ฅ์ฝ๋ ๊ตฌ๋ถ์ |
EP | ์๋ธ์คํฌ๋ฆฝํธ์ ๊ตฌ๋ถ์ |
RLENGTH | match ํจ์๋ก ์ผ์นํ๋ ๋ฌธ์์ด์ ๊ธธ์ด |
RSTART | match ํจ์๋ก ์ผ์นํ๋ ๋ฌธ์์ด์ ์คํ์ |
awk ๋ด์ฅํจ์
$ awk '{ print ("name leng : " length($1), "substr(0,3) : " substr($1,0,3)) }' filename
awk ๋ฌธ์์ด ํจ์
ํจ์๋ช | ์ค๋ช |
gsub(r, s) | ์
๋ ฅ ๋ฌธ์์ด ์ ๋ถ์ ๊ฑธ์ณ ์ ๊ท์ํํ r์ ๋ฌธ์์ด s๋ก ์นํํ๋ค. |
gsub(r, s1, s2) | ์
๋ ฅ๋ฌธ์์ด s2 ์์ ์ ๊ท์ ํํ r์ ๋ฌธ์์ด s1 ์ผ๋ก ์นํํ๋ค. |
index(s1, s2) | s1์์ s2์ ์์น๋ฅผ ๋๊ฒจ์ค๋ค. ์๋ค๋ฉด 0 |
length(arg) | ์ธ์์ ๊ธธ์ด๋ฅผ ๋๊ฒจ์ค๋ค. |
match(s, r) | ๋ฌธ์์ด s์์ ์ ๊ท์ํํ r๊ณผ ๋งค์นญ ๋๋ ๋ถ๋ถ์ ์์น๋ฅผ ๋๊ฒจ์ค๋ค. |
split(string, array[, seperator]) | ๊ตฌ๋ถ์๋ฅผ ๊ธฐ์ค์ผ๋ก(๊ธฐ๋ณธ:๊ณต๋ฐฑ)ํด์ ์ง์ ํ ๋ฌธ์์ด์ ๋ฐฐ์ด๋ก ๋ง๋ ๋ค. |
sub(r, s) , sub(r, s1, s2) | gsub ์ ๋์ผ ์ ๊ท์์ํํ๊ณผ ์ผ์นํ๋ ๋ฌธ์์ด์ด ์ฌ๋ฌ๊ฐ๋ผ๋ ์ฒ์ ํ ๋ฌธ์์ด๋ง ์นํ |
substr(s, m) | ๋ฌธ์์ด s ์์ m๋ฒ์งธ ์์น์์ ๋๊น์ง ๋ฌธ์์ด์ ๋๊ฒจ์ค๋ค. |
substr(s, m, n) | ๋ฌธ์์ด s ์์ m๋ฒ์งธ ๋ถํฐ n๋ฒ์งธ๊น์ง์ ๋ฌธ์์ด์ ๋๊ฒจ์ค๋ค |
tolower(string) | ๋๋ฌธ์๋ฅผ ์๋ฌธ์๋ก ๋ฐ๊พผ๋ค. |
toupper(string) | ์๋ฌธ์๋ฅผ ๋๋ถ์๋ก ๋ฐ๊พผ๋ค. |
awk ์ํ ํจ์
ํจ์๋ช | ์ค๋ช |
atan2(x, y) | archtangent ๊ฐ |
cos(x) | cos ๊ฐ |
exp(x) | ์์ฐ๋์ e์ ์ ๊ณฑ |
int(x) | ์ ์ํ์ผ๋ก ๋ฐํ |
log(x) | ๋ก๊ทธ |
rand() | 0์์ 1๊น์ง์ ๋๋ค์ |
sin(x) | sin ๊ฐ |
sqrt(x) | ์ ๊ณฑ๊ทผ |
srand(expr) | ์ธ์๋ฅผ ๊ฐ์ง ๋์(์์ผ๋ฉด ์๊ฐ์ ๊ฐ์ง๊ณ ๋์ ๋ฐ์) |
awk ์ ์ถ๋ ฅ ํจ์
ํจ์๋ช | ์ค๋ช |
close(filename) | ์ง์ ํ ํ์ผ์ ๋ซ๋๋ค. |
close(cmd) | ์ง์ ํ ๋ช ๋ น์ด ํ์ดํ๋ฅผ ๋ซ๋๋ค. |
delete array[element] | ์ง์ ํ ๋ฐฐ์ด์์๋ฅผ ์ง์ด๋ค. |
getline() | ๋ค์ ๋ ์ฝ๋๋ฅผ ์ฝ์ด ๋ค์ธ๋ค. |
getline [variable] [< "filename"] | ํ์ผ์์ ์ฝ์ด๋๋ฆฐ๋ค. |
next | ๋ค์ ๋ ์ฝ๋๋ฅผ ์ ๋ ฅ๋ฐ๋๋ค. |
print [args] [> "filename"] | ์ธ์๋ฅผ ์ถ๋ ฅํ๋ค |
printf "format" [,exp] [> "filename"] | ํ์์ ๋ง์ถฐ ์ธ์๋ฅผ ์ถ๋ ฅํ๋ค. |
sprintf(format [,exp]) | printf์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ฌ์ฉ๋์ง๋ง ๊ฐ์ ๋ฆฌํดํ๊ธฐ๋ง ํ๊ณ ์ถ๋ ฅ์ ํ์ง ์๋๋ค. |
system(cmd) | ์์คํ ๋ด๋ถ ๋ช ๋ น์ด๋ฅผ ์คํํ๋ค. |
AWK ๋ช ๋ น ์ฌ์ฉ ์์
ํ๋ ๊ฐ ์ถ๋ ฅ ํ๊ธฐ ($์ซ์)
$ cat file.txt
1 ppotta 30 40 50
2 soft 60 70 80
3 prog 90 10 20
$ awk '{ print $1,$2 }' ./file.txt # ์ฒซ ๋ฒ์งธ, ๋ ๋ฒ์งธ ํ๋ ๊ฐ ์ถ๋ ฅ.
1 ppotta
2 soft
3 prog
$ awk '{ print $0 }' ./file.txt # ๋ ์ฝ๋ ์ถ๋ ฅ.
1 ppotta 30 40 50
2 soft 60 70 80
3 prog 90 10 20
$ cat file.txt
1 ppotta 30 40 50
2 soft 60 70 80
3 prog 90 10 20
$ awk '{print "no:"$1, "user:"$2}' ./file.txt # ํ๋ ๊ฐ์ ๋ฌธ์์ด์ ํจ๊ป ์ถ๋ ฅ
no:1 user:ppotta
no:2 user:soft
no:3 user:prog
ํจํด ์ด์ฉ (์ ๊ท์ / ๋น๊ต์)
$ cat file.txt
1 ppotta 30 40 50
2 soft 60 70 80
3 prog 90 10 20
$ awk '/pp/' ./file.txt # "pp" ๊ฐ ํฌํจ๋ ๋ ์ฝ๋๋ง ์ ํจ.
1 ppotta 30 40 50
$ awk '/[2-3]0/' ./file.txt # 20, 30 ์ด ํฌํจ๋ ๋ ์ฝ๋๋ง ์ ํจ.
1 ppotta 30 40 50
3 prog 90 10 20
$ cat file.txt
1 ppotta 30 40 50
2 soft 60 70 80
3 prog 90 10 20
$ awk '$1 == 2 { print $2 }' ./file.txt # ์ฒซ ๋ฒ์งธ ํ๋๊ฐ 2์ธ ๋ ์ฝ๋์ ๋ ๋ฒ์งธ ํ๋ ์ถ๋ ฅ.
soft
$ awk '$3 > 70 { print $0 }' ./file.txt # ์ธ ๋ฒ์งธ ํ๋๊ฐ 70๋ณด๋ค ํฐ ๋ ์ฝ๋ ์ถ๋ ฅ.
3 prog 90 10 20
$ awk '$3 == 30 && $4 ==40 { print $2 }' file.txt # ์ธ ๋ฒ์งธ ํ๋๊ฐ 30์ด๊ณ ๋ค ๋ฒ์งธ ํ๋๊ฐ 40์ธ ๋ ์ฝ๋์ ๋ ๋ฒ์งธ ํ๋ ์ถ๋ ฅ.
ppotta
$ cat str.txt
a b c
d e f
g h i
$ cat c.txt | awk '$1=="a"' str.txt # ํน์ ๋ ์ฝ๋๋ง ์ถ๋ ฅ
a b c
$ cat c.txt | awk '$1!="a"' str.txt # ํน์ ๋ ์ฝ๋ ์ ์ธ ์ถ๋ ฅ
d e f
g h i
$ cat c.txt | awk '$2~/^e/' str.txt # ํจํด๋น๊ต. $2ํ๋๊ฐ ๋ฌธ์e ๋ก ์์ํ๋ ๋ ์ฝ๋๋ง ์ถ๋ ฅ
d e f
CSVํ์ผ ์ฒ๋ฆฌํ๊ธฐ (-F ์ต์ )
์ผํ๋ก ๊ตฌ๋ถ๋ ๊ฐ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด์๋ -F ์ต์ ์์ ๊ตฌ๋ถ ๊ธฐํธ๋ฅผ ์ฌ์ง์ ํ๋ฉด ๋๋ค.
$ cat test.csv
1,2,3
4,5,6
7,8,9
$ cat b.txt | awk -F, '{print $1}' # -F์ต์
์ ํตํด , ๋ก ๊ตฌ๋ถ๊ธฐํธ๋ฅผ ์ฌ์ง์ ํ๊ณ $1ํ๋๋ง ์ถ๋ ฅ
1
4
7
ํ ๋ฒํธ ์ถ๋ ฅํ๊ธฐ (NR ๋ด์ฅ๋ณ์)
ํ ๋ฒํธ๋ฅผ ์ถ๋ ฅํ๊ธฐ ์ํด์๋ print ์ NR ์ต์ ์ ์ถ๊ฐํ๋ค.
- NR์ awk ๋ด์ฅ๋ณ์๋ก์ ๋ช๋ฒ์งธ ๋ ์ฝ๋์ธ์ง ์๋ฒ ์ถ๋ ฅํ๋ค
- $0 ์ ๋ ์ฝ๋ ํ ์ค ์ถ๋ ฅ
$ cat test.csv
1,2,3
4,5,6
7,8,9
$ cat test.csv | awk -F, '{print NR " " $0;}'
1 1,2,3
2 4,5,6
3 7,8,9
$ awk_example]$ cat test.csv | awk -F, '{print NR-1 " " $0;}' # 0๋ถํฐ ์์
0 1,2,3
1 4,5,6
2 7,8,9
์ฐ์ ๊ณ์ฐ
$ cat num.txt
100
200
300
400
500
$ awk '{sum+=$1} END {print sum}' num.txt # ํฉ๊ณ ๊ณ์ฐ. ENDํจํด์ ํตํด ๋ ์ฝ๋๋ฅผ ๋ชจ๋ ๋๋ ๋ ํ ๋ง์ง๋ง์ ํฉ์ ์ถ๋ ฅ
1500
$ awk '{sum+=$1} END {print sum/NR}' num.txt # ํ๊ท ๊ณ์ฐ. ๋ด์ฅ๋ณ์ NR์ ์ถ๋ ฅ์๋ฒ๊ฐ. ์ฆ ๋ ์ฝ๋ ๊ฐฏ์๋ฅผ ์๋ฏธ
300
## NR==1 {max=$1} ์ด๋ผ๋ ๋ป์ ์ต๋/์ต์๋ฅผ ๊ตฌํ๊ธฐ ์ํด ์ด๊น๊ฐ์ ์ค์ ํ๋ ๋ก์ง. ์ถ๋ ฅ์๋ฒ์ด ์ฒซ๋ฒ์งธ ์ผ๋๋ง max๋ณ์์ $1๊ฐ ์ ์ฅ
$ awk 'NR==1 {max=$1} {if($1 > max) max = $1} END {print max}' num.txt # ์ต๋๊ฐ ๊ณ์ฐ
500
$ awk 'NR==1 {min=$1} {if($1 < max) min = $1} END {print min}' d.txt # ์ต์๊ฐ ๊ณ์ฐ
100
$ cat file.txt
1 ppotta 30 40 50
2 soft 60 70 80
3 prog 90 10 20
$ awk '{ sum = 0 } {sum += ($3+$4+$5) } { print $0, sum, sum/NR }' ./file.txt # ํฉ๊ณ์ ํ๊ท ๊ตฌํ๊ธฐ
1 ppotta 30 40 50 120 40
2 soft 60 70 80 210 70
3 prog 90 10 20 120 40
printf ํฌ๋งทํ
C์ธ์ด์ printf() ํจ์์๋ ํฌ๋งท์ง์ ์๊ฐ ์๋๋ฐ, ์ด๋ฅผํตํด ์ถ๋ ฅ ์นธ ์ ๋๋น๋ฅผ ์กฐ์ ํ ์ ์๋ค.
awk์์๋ ๋๊ฐ์ด ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
$ cat file.txt
1 ppotta 30 40 50
2 soft 60 70 80
3 prog 90 10 20
$ awk '{ printf "%-3s %-8s %-4s %-4s %-4s\n", $1, $2, $3, $4, $5}' file.txt
1 ppotta 30 40 50
2 soft 60 70 80
3 prog 90 10 20
์กฐ๊ฑด๋ฌธ
$ cat file.txt
name phone birth sex score
reakwon 010-1234-1234 1981-01-01 M 100
sim 010-4321-4321 1999-09-09 F 88
$ awk '{ if ( $5 >= 80 ) print ($0) }' file.txt # score๊ฐ 80์ ์ด์ ๋ ์ฝ๋๋ง ์ถ๋ ฅ
$ awk '$5 >= 80 { print $0 }' ./awk_test_file.txt # action๋ถ๋ถ์ if๋ฅผ ์ฐ๋ pattern๋ถ๋ถ์ ๋น๊ต์ฐ์ฐ์๋ฅผ ์ฐ๋ ๊ฒฐ๊ณผ๋ ๋์ผ
๋ฃจํ๋ฌธ
NF : awk ๋ด์ฅ๋ณ์. ํ์ฌ ์ค์ ํ๋ ๊ฐฏ์
$ cat file.txt
1 ppotta 30 40 50
2 soft 60 70 80
3 prog 90 10 20
$ awk '{ for (i=3; i<=NF; i++) total += $i }; END { print "TOTAL : "total }' ./file.txt # ๊ฐ ๋ ์ฝ๋์ $3 ~ $5 ํ๋ ์ดํฉ
TOTAL : 450
๋ด์ฅํจ์ ์ฌ์ฉ
$ cat e.txt
a
ab
abc
abcd
abcde
$ cat e.txt | awk '{print length();}' # ๊ฐ ํ์ ๋ฌธ์์ ๊ตฌํ๊ธฐ
1
2
3
4
5
ํ์ดํ ์กฐํฉ
$ cat file.txt
1 ppotta 30 40 50
2 soft 60 70 80
3 prog 90 10 20
$ awk '{ print $0 }' file.txt | sort -r # awk ์ถ๋ ฅ ๋ ์ฝ๋๋ฅผ ํ์ดํ๋ก ๋ณด๋ด ์ญ์์ผ๋ก ์ ๋ ฌ.
3 prog 90 10 20
2 soft 60 70 80
1 ppotta 30 40 50
# ์ฐธ๊ณ ์๋ฃ
https://zzsza.github.io/development/2017/12/20/linux-6/
https://reakwon.tistory.com/163
https://recipes4dev.tistory.com/171
http://egloos.zum.com/bosoa/v/3932702
https://blog.muabow.com/185
https://techgoeasy.com/unix-awk-command/
https://jhnyang.tistory.com/494