[bash: awk] 문자열을 검색해서 일치하는 부분만 출력하기(match, substr) 리눅스 bash script

awk에서 특정 문자열 패턴과 일치하는 부분이 있을 경우, 일치하는 부분만 출력하는 방법이다. grep에서 -o 옵션으로 일치하는 부분만 골라서 출력하는 것과 동일한 기능이나(grep의 -o 옵션에 대한 내용은 이전 게시물을 참고하자. 여기로), awk에서는 좀 더 복잡한 작업들과 조합해서 사용할 수 있으므로 알아두면 편리하다.

아래의 예시를 보자. 입력된 행에 문자열 "abc"가 있는지 확인하여 있을 경우 해당 부분만 출력하는 경우다.

echo "abcdefg" | awk 'match($0,/abc/) { print substr($0,RSTART,RLENGTH) }'
abc

match 함수를 이용하여 일치하는 부분이 있는지 확인한 후에 문자열 일부를 출력하기 위해 substr 함수를 사용했다. match 함수에서 행 전체($0)를 대상으로 문자열 abc를 검색하고, 만약 일치하는 부분이 있으면 print 명령이 실행된다.

match 함수를 호출하면 일치하는 부분의 시작 위치와 길이는 내부 변수인 RSTART, RLENGTH에 각각 저장되므로, substr 함수의 인자(argument)로 사용하면 된다. (awk의 substr 함수에 대한 좀 더 자세한 내용은 이전 게시물을 참고하자. 여기로)

조금 더 복잡한 상황을 생각해 보자. 탭(tab)으로 구분된 입력에서 두번째 항목(field)에 연속되는 3개의 수자가 있는지 확인하고, 만약 있으면 첫번째 항목과 두번째 항목을 출력하는 경우다.

echo -e "abc\tdef012345\tABC" | awk -F '\t' 'match($2,/[0-9][0-9][0-9]/) { print $1 "\t" substr($2,RSTART,RLENGTH) }'
abc  012

awk의 -F 옵션을 이용하여 구분자를 탭으로 지정해 주었다. match 함수에서는 대상을 두번째 항목($2)으로 한정하고 수자를 찾아야 하므로 정규표현식(regular expression, regex)을 사용하여 패턴을 지정했다. 출력하는 부분의 substr 함수의 대상 항목도 match 함수와 일치시켜 $2로 지정해 준다는 점에 유의.

test.txt 파일에 저장된 내용을 가지고 위와 같은 작업을 한다면 아래와 같이 될 것이다.  

awk -F '\t' 'match($2,/[0-9][0-9][0-9]/) { print $1 "\t" substr($2,RSTART,RLENGTH) }' test.txt

여러 항목이 있는 자료를 읽어서 특정 항목에서 내가 원하는 부분만 추출하여 나머지 항목과 함께 출력하고 싶을 경우 매우 요긴하게 활용할 수 있다.



[bash: awk] 항목의 합계를 계산할 때 예외 처리 리눅스 bash script

awk를 이용해서 합계를 구할 때, 입력이 유효하지 않은 경우가 발생할 수 있다. 예를 들어 특정 파일에서 grep으로 특정 항목만 추출한 후에 해당 항목의 합계를 구하려는데, 그 항목 자체가 파일에서 존재하지 않는 경우다. awk를 이용한 항목별 합계 계산 방법은 이전 게시물을 참고하자. 여기로

예를 하나 생각해 보자. my_data.txt의 파일이 아래와 같다.

# my_data.txt 파일 내용 확인 (구분자는 탭)
cat my_data.txt
2018.1.3 apple 10
2018.1.3 orange 3
2018.3.10 apple 2

위의 파일에 대해서 사과(apple)가 몇개 팔렸는지만 궁금하다면 아래와 같은 작업을 할 수 있다.

# 사과(apple) 항목의 합계 계산
cat my_data.txt | grep apple | awk -F '\t' '{ res+=$3 } END { print res }'
12

물론 grep을 사용하지 않고 awk 안에서도 특정 항목을 걸러낼 수 있겠지만(이에 대한 자세한 내용은 이전 게시물을 참고하자. 여기로), 합계를 구하기 전에 뭔가 앞쪽에 이것 저것 복잡한 작업이 있고 그 중간에 grep이 포함될 수도 있으므로 상황에 따라 위의 예시가 유효할 수 있다.

사과에 대해서는 문제가 없는데, 만약 파일에 없는 망고(mango)가 몇개 팔렸는지 구하려 한다면 문제가 발생할 수 있다.

# 망고(mango) 항목의 합계 계산 (my_data.txt에 없는 항목)
cat my_data.txt | grep mango | awk -F '\t' '{ res+=$3 } END { print res }'

위의 경우 출력값이 "0"이 아니라 아예 나오지 않는다. 만약 이 작업 결과를 변수에 저장하고 나서 유효한 수자로 가정하여 수치 연산을 하려 한다면 오류가 발생할 것이다.

# 망고 항목의 합계를 변수 mango_sum에 저장
mango_sum=`cat my_data.txt | grep mango | awk -F '\t' '{ res+=$3 } END { print res }'`

# 결과값에 대한 연산 시도 (오류 발생)
echo "$mango_sum / 10" | bc
(standard_in) 1: syntax error

따라서 이러한 상황이 발생할 가능성이 있다면, 값이 유효하지 않을 경우에는 "0"이라고 출력하도록 만들어 주는 것이 좋겠다. awk에서 결과를 출력하는 부분에 if 조건문을 사용하면 된다. awk에서 합계를 저장한 변수 res의 값이 0보다 크면 res를 그대로 출력하고, 그렇지 않으면 "0"을 출력하도록 아래와 같이 변경한다.

# 망고(mango) 항목의 합계 계산
cat my_data.txt | grep mango | awk -F '\t' '{ res+=$3 } END { if (res>0) { print res } else { print "0" }'
0

복잡한 스크립트에서 합계를 구해서 나중에 다른 작업에 활용해야 하는 경우엔 위와 같이 결과값이 항상 유효하도록 처리해 주자.



탈원전의 선구자 독일 근황 일기/잡담

원문기사는 여기로.

2017년 10월에 포브스(Forbes)에 게재된 기사다. 1년전 기사지만 현재 상황이 별반 나아진 것이 없으므로 충분히 의미가 있다고 생각된다. 주요 내용은 아래와 같다.


신재생에너지가 독일의 탄소배출량을 줄이지 못하는 이유는 무엇인가?

독일의 전력생산 비중에서 신재생에너지는 거의 30%에 달하고 있으며 설치 용량 기준으로는 50%를 넘어섰다. 그러나 동시에 재생에너지의 불규칙적인 전력생산을 보상하기 위한 목적으로  석탄화력발전도 30% 증가했으며 프랑스 등 다른 유럽 국가로부터 전력을 수입하고 있는 실정이다.

독일의 1인당 탄소배출량은 2013년에서 2015년 사이에 오히려 소폭 증가했다. 독일은 실제 필요한 것보다 더 많은 양의 전력을 생산하고 있으며 운송업계의 기름 소비에 대해서는 별다른 조치를 취하지 않고 있다.

신재생에너지는 전체 탄소배출량에 별다른 영향을 주지 못한다. 신재생에너지가 생산하는 전력이 국가의 전력소요량을 초과하더라도 생산량의 변동이 커서 결국 석탄화력발전소를 계속 운영할 수 밖에 없기 때문이다. 독일은 석탄화력발전소를 계속 유지할 수밖에 없고 이중 절반이 석탄 중에 가장 더러운 갈탄(lignite)을 사용한다.

2016년 기준으로 유럽의 가장 심각한 대기오염원 10개중 7개가 독일의 화력발전소였다.

독일은 탄소배출이 아예 없는 원자력발전소를 수년에 걸쳐 폐기하고 있으므로 상황은 더욱 악화될 것이다. 독일에서 탈원전이 이루어지면 풍력발전으로 얻는 전력량 전체에 해당하는 규모의 생산력이 사라진다. 이러한 문제 때문에 저명한 기후학자들은 원자력을 유지해야 한다고, 또는 오히려 증가시켜야 한다고 경고하고 있는 것이다.

바나듐 흐름 전지(vanadium flow battery)나  양수발전장치(pumped hydro storage) 등 전력저장기술이 도움이 될 수 있긴 하겠지만, 저장해야 하는 전력량이 너무나 커서 기후온난화를 따라잡기엔 역부족이다.

또한 이러한 저장기술은 비용이 높아서 일부 국가는 정부보조금을 지급하기도 하는데, 결국은 이것도 세금으로 마련해야 하므로 문제가 달라지는 것은 아니다.

미국, 프랑스, 독일의 지난 10년간 탄소배출량을 비교해 보면, 대부분의 전력을 원자력으로 생산하는 프랑스가 가장 낮다. 세 국가중에 1인당 탄소배출량이 가장 높은 국가는 미국인데 전력생산의 3분의 2가 여전히 화석연료에 기반을 두고 있기 때문이다. 독일의 화석연료 의존도는 50% 정도로 중간이다.

선진국의 탄소배출량은 전반적으로 줄어들고 있는데, 에너지 효율성이 높아졌기 때문이다. 2008년에는 세계적인 불황으로 인하여 배출량이 눈에 띄게 줄었다.

그러나 미국의 탄소배출량이 급격히 감소한 가장 큰 이유는 전력생산에서 석탄을 천연가스로 대체했기 때문이다.

반면에 독일의 탄소배출량 감소는 미미하다. 신재생에너지를 급격히 늘리고 전체 에너지 소비량이 줄어들었다는 점을 고려하면 이것은 이상하게 보일 수도 있다.

독일은 1990년에서 2020년까지 탄소배출량을 40% 감축할 계획으로 신재생에너지 비중을 급격히 늘렸고 그 과정에서 무려 8천억달러의 정부 보조금을 지출했으나 목표를 달성할 가능성은 불확실해 보인다.

베를린의 에너지 관련 싱크탱크인 아고라 에네르기벤데(Agora Energiewende)도 이 계획은 약간의 미달 정도가 아니라 대실패가 될 것으로 예측했다.

에너지와 기후에 대해서 이해하고 있다면 신재생에너지, 원자력, 수력 등 탄소배출량이 낮은 에너지원을 최대한 빨리 총동원해야 변화를 이끌어낼 수 있다는 것을 알고 있을 것이다.

그렇게 하지 않는다면 그것은 그저 흥미로운 실험일 뿐이다.




1 2 3 4 5 6 7 8 9 10 다음

Google Analytics


B-Side


adsense(w160_h600)2

통계 위젯 (화이트)

154832
4935
1595027

ad_widget_2