2011. 10. 19. 05:31

"빛보다 빠른 뉴트리노" 실험이 잘못된 게 밝혀졌다구요?

갑자기 인터넷에 온통 OPERA의 뉴트리노 실험이 잘못되었다는 결론이 나왔다는 소식들이 넘쳐난다.
내용을 보면 네델란드  University of Groningen 대학의 Ronald Van Elburg가 arvix에 올린 

Time-of-flight between a Source and a Detector observed from a Satellite 

라는 논문이 위 실험의 에러를 찾아냈다는 것이다. 

이미 빛보다 빠른 뉴트리노를 설명하는 수 십편의 논문과 문제점을 지적하는 수십편의 논문이 나왔다는데 ( 확인은 안해봤으나 믿을 만한 사람들이 한얘기, 굳이 안 찾아봄 ), 얼마나 잘 쓴 논문이길래 시끄러운가 하고,,
이미 이론과 많이 멀어진 실험물리학자이지만 몸소 한번 들여다 보기로 했다.

그런데!!!

오!!!!!!!, 이건!!!!!!!


쉽다.... 

 
수식도 몇개 안되고 특수 상대성이론 반나절 공부하면 따라갈 수 있는 전개!!
왜 인터넷이 떠들석해 졌는지 이해가 간다. 다른 논문들은,, 이해할 수 없으니.... 

이렇게 쉬운 수식으로 뭘 찾아낸걸까,, 천잰데..

하지만, 내용이 선뜻 동의하기 어렵다.
주된 내용은 인공위성에서 출발한 전파가 GPS수신기에 도달하는 시간에 대해서 얘기하고 있는것 같은데.
일단,  GPS 시간 측정이라는건, 여러 개의 위성을 이용해 계산 하는 것이기 때문에 
( 내시계와  GPS 시계가 동기화 되어 있는게 아니라면, 하나의 위성으로는 시간과 위치를 알 수  없고, 4개 부터 가능하다 )  두개의 GPS수신기에 대해서 2*Error = 64ns 라는건,  좀 억지스러워 보인다 ( 이건 논문에 따르면 한개의 gps위성이 첫번째 수신기와 두번째 수신기 사이에서 있을때 얘기.. 라고 추측됨, 확실한건 아무것도 없음 :-) )

무엇보다

 

, 라는 건, 선뜻,, 이상하다 ( 라는건 뭔소린지 모르겠다 )  ( s는 인공위성 rest frame이란 뜻이고,  S는 거리 
τ는 도달 시간 ). 
 

특히

결론인 t = S/(c+v) 쯤 오면 .. 이건 이동하는 물체에서 발사된 빛은 속도가 c보다 빠르다는 건가?  도플러 효과얘기라면 몰라도....

흠 솔직히 모르겠다, 실험한답시고 공부를 안했더니 다 잊어먹었다.
CERN에 있으면서 특수상대성 이론도 헷갈린다니 쪽팔린다. 공부해야지. 


추가.
물론 OPERA 실험 결과가 틀렸다는데 100$건다. 이건 그냥 배팅.
하지만 틀렸더라도 문제가 무엇인지를 찾기가 쉽지가 않다는 건 확실하다. 
실험 물리학자들이 놀고 먹으면서 결과 내는게 아니거든.

 
2009. 3. 25. 09:00

두 문자열에서 중복되는 부분 찾기

sng2nara님의 낚시에 파닥파닥 낚여서 만들어보게 되었다.

문제는 다음과 같은 문자열들이 있을때

my $common = 'ABC';
my @str;
$str[0] = 'AA BBCD ABC bbbc aaaa';
$str[1] = 'BBAA BBCD ABC bbb';
$str[2] = '123BBAA BBCD ABC bbFSKFSJLK';
$str[3] = '239I2P3IBBAA BBCD ABC bbb FLSKJFLSKJDFLJS';
$str[4] = 'ABC bbb';


@str의 문자열들에서 ABC를 포함하면서 공통되는 가장 큰 문자열 셋을 찾는 것.
이경우네는 ABC bbb 가 된다.

물론 효율을 따지면,, 한글자한글자 비교해야 겠지만
일단 효율 무시, 정규표현식을 써보자

두 문자열의 공통된 부분을 찾는 건 꽤 쉽다. 일단 두 문자열을 합친 다음에 다음처럼 만들면 된다.

($max_common) = (($str[0].$str[1]) =~ /^.*?(.*$common.*).*?\1.*?$/)


자세한 설명은.. 생략
한가지만 얘기하자면 첫번째 ()에서 찾은것이 \1이 된다는 정도.
사실 경우에 따라 몇가지 버그를 가지고 있기는 하다
한 문자열에 ABC가 여러개 있다면 우리가 원하는 대로 나오지 않을 수 있다.
이경우에는 한 문자열에 ABC가 하나만 있다고 가정하자. (혹은 그렇게 만들 루틴을 가지고 있다고)

그럼 여러개의 문자열에 대해서는 어떻게 할까?
여러개의 문자열을 모두 합쳐서 찾으면 좋겠지만, 그럼 위와 같은 문제가 다시 발생한다.
어쩔수 없이 정규표현식을 문자열 개수만큼 돌려야 한다.

my $max_common = shift @str;
($max_common) = (($max_common.$_) =~ /^.*?(.*$common.*).*?\1.*?$/) for @str;
print $max_common;

우왕 굿.

그러나 효율에는 심각한 문제가 있다.
이 정규표현식의 경우는 backtracking을 이용해서 꽤 과도하게 검색을 하기 때문에 긴 문자열에는 적합하지 않다.

테스트로 17kbytes 문서 두개를 이용해서 비교해 봤는데 10분 동안 돌린후에 테스트를 포기했다.
문자열의 길이에 대해 어느정도 효율을 가지는지 테스트해보고 싶지만,, 귀차니즘으로 생량.

그것은 그대의 손에!!















'Perl Recipe' 카테고리의 다른 글

일전한 글자수의 단어 세기  (7) 2009.03.24
원라인 펄 놀이 - 첫줄 빼고 sort  (0) 2008.04.17
여러파일을 sorting 하기  (0) 2007.12.11
리스트 비교  (0) 2007.11.06
한꺼번에 많은 파일 지우는 세가지 방법  (1) 2007.11.05
2009. 3. 24. 18:41

일전한 글자수의 단어 세기

http://kldp.org/node/104031 를 보고 aero님과 얘기하다가 시작되었다.

문제의 내용(사실은 문제의 일부)는 다음과 같은 문자열에서 AA, AT, AG, AC....의 개수를 세는것

ATCGATCGATCGATAAAC
GATCTAGCTAGCATAACC

앞에서 부터 두글자씩 세는건 아주 단순하다.

$count{$_}++ while $str =~ /(..)/g


하지만 aero님의 문제제기,

앞에서 부터 2글자씩 세는 것이 아니라 임의의 두글자라면 어떻하죠?

먼저 aero님의 구현은
 while ( $str =~ /(..)/g ) {
    $count{$1}++;
    pos $str -= 1;
}
오 멋지다.  마지막으로 두글자의 다음 위치인 pos($str) 의 위치를 뒤로 한글자 돌려서 다시 검색한다.
2글자가 아니라 N글자라면 pos $str -= N-1 이라고 해주고 정규표현식을 조금 바꿔주면 끝.

나의 구현도 매우 비슷하다. 다만 perl 정규표현식의 \G앵커를 사용했다는 정도

pos($str) = 1;
while ( $str =~ /(.\G.)g ) {
    $count{$1}++;
}


처음 pos를 정해놓고 현재 pos위치를 의미하는 \G앵커를 이용하여 검색.. (자세한 내용은 perldoc perlre)
N글자의 단어를 찾으려면 pos위치를 N-1로 하고 /(.{$N-1}\G.)/g 로 바꾸면 끝..
N글자에서는 aero님의 코드가,, 몇글자 짧아지긴 하겠군요

글자수도 거의 같고, 효율도 거의 비슷하겠군.

원라이너 용으로 내 코드를 정리해 보면

perl -nle'pos=1;$c{$1}++ while /(.\G.)/g}{print"$_\t$c{$_}"for sort keys %c' filename


되겠다.

추가로 Luz♡lunA 님의 말씀

 <Luz♡lunA> [hanIRC] c식으로 하면 그냥 한글자씩 뽑으면서 prev를 저장해가면서 진행하면.....

맞습니다.
이게 정석인거죠.

2008. 6. 5. 17:45

정규표현식과 코드골프에 관한 IRC로그

어제 IRC에서 나온 뼈가되고 살이되는 펄 얘기 입니다.
주로 간단한 정규 표현식으로 뭘 할 수 있는지 에 관한 얘기죠.
재미있는 로그라 모두 긁어왔는데 좀 기네요. 132줄!!


하지만 읽기 귀찮으신 분들을 위해서 정리도 해드리는 센스!!
두개의 문제가 나왔는데

1.  연숙된 문자열에서 숫자의 앞뒤에 공백 넣기

"11aa11bbcc222d" 를 "11 aa 11 bbbb 222 d" 로 바꾸는 거죠.
간단한 문제이니 만큼 답도 간단합니다.
s/(\d+)/ $1 /g

또는
perl -pe 's/(\d+)/ $1 /g'


2. perldoc 문서 이름을 위키네임으로 바꾸기

twiki에 perldoc관련 플러그인을 만들다가 나온 문제입니다.
perldoc은 perlsub, perlreftut처럼 perl로 시작하고 모두 소문자로 되어있는데
이걸 PerlSub, PerlReftut 처럼 perl의 P와 perl 뒤으 문자 하나 총 2개의 대문자를 가진 문자열로 바꾸는 문제입니다.
다음 코드들에서 print가 나왔다가 안나왔다가 하는 이유는 저는 문자열 반환이 목적이었고, saillinux님과 aero님은 출력이 목적이었기 때문입니다. 알아서 잘 해석해주세요^^
 문자열이 $_에 저장되어 있다고 가정하면
처음에 나온 코드는  saillinux 님의
print "Perl".join '', map {ucfirst}split(/perl/, "$_");

오 훌륭하군요,
약간 바꿔보면
 print join '', map ucfirst, /(perl)(.*)/;

이렇게도 가능하지요.

제가 정규표현식을 써서 만든 코드는 
s/(perl)(.*)/ucfirst$1.ucfirst$2/e


이걸 코드 골프용으로 고치면,, 보기에는 지저분 하지만
/l/;ucfirst$`.'l'.ucfirst$

이렇게 만들 수 있습니다.

이걸 보여드렸더니 aero님께서 다른 아이디어를 제시하시더군요
print map "\u$_",/(perl)(.*)/


호~~ \u가 있었군요. 저는 \U는 알고 있었는데, \U는 한문자에만 적용되는 것이 아니라 \E와 쌍을 이루는 것이어서 못쓰고 있었거든요. 그래서.. 잽싸리 저도 코드를 바꿔봤습니다.
/l/;"\u$`l\u$'"

오호. 마지막 코드를 보신 aero님께서 한 말씀 날려주시더군요
ㅂㅌ

추가:2008/06/08
오늘 아침에 나온 아이디어입니다.
s/(perl|.*)/\u$1/g

우왕~~


코드에 대한 자세한 설명은 saillinux 님께서 해주시리라 믿습니다.
2008. 4. 17. 09:26

원라인 펄 놀이 - 첫줄 빼고 sort

#perl 에서 saillinux님과 JEEN님의 "쉘에서 파일의 첫 줄을 빼고 소팅하려면"이라는 대화내용을 듣다가 이를 위한 몇가지 아이디어가 떠롤랐다.

파일의 첫줄을 출력한다 던가 마지막 줄을 출력하는 것은 head나 tail로 쉽게 할 수 있지만 첫 줄을 빼고 출력하는 방법은?

1. 다음과 같은 saillinux 님이 가르쳐 주신 위대한 방법도 있다.
   
tail -n `expr \`wc -l file-to-sort | awk '{ print $1 }'\` - 1` file.txt
오.. 왠만한 내공이 아니고는 만들기도 힘든 구문!! `` 안에 ``를 쓰는 센스!!
옛날 연구실의 한 선배는 awk 두개를 써서 더블 루프을 구현하기도 했었다.

그러나 다행히도 더 간단한 방법이 있다.

2. tail
tail -n +2 file.txt
언제부턴지는 모르겠지만 tail 에 "앞에서 몇줄부터" 출력해주는 기능이 생겼다.
간단히 +를 숫자앞에 붙이면 끝이다. 문제는, 이 기능이 언제부터 생긴건지 모르기 때문에 호환성이 좀 걱정된다는 사실.

3. sed
sed -n '2,$p' file.txt 
오래 전부터 이런 일은 awk,  sed 가 강자였지..

그러나 진정한 강자는 따로 있는 법

4. perl
perl -ne'$.>1 and print' file.txt
perl -ne'2..-1 and print' file.txt
perl -ne'2..eof and print' file.txt
오.. 가장 "리더블" 하지 않은가!!(물론, $.을 알아야 하지만)

이제 남은 건 sort 하는 일뿐!! 이건 뭐... 첫줄은 출력하고 나머지는 sort하면 된다.
head -1 file.txt; perl -ne'$.>1 and print' file.txt | sort

그러나 여기서 끝내기엔 너무 쉬운 내용을 너무 길게 썼다.
뭔가 더해보자.
소팅하고 출력하는 것을 펄 안에서 끝내보자.
목표는 : 텍스트를 다 배열에 저장하여 첫줄 빼고 소팅한 다음 출력한다.

perl -ne'push @L, $_;END{print $L[0],sort @L[1..$#L];}' file.txt

잘 되긴 하는데,, 뭔가 아쉬운 이 느낌은 뭘까, 너무 당연한 코드라서 재미가 없다.
게다가 매줄마다 push를 하는건,, 너무 비싸다는 생각이!!
모든 줄을 한꺼번에 배열에 넣을 방법은 없을까?
음, 이럴땐 첨부터 꽁수를 생각해보자.
perl -ne'$f=$_;@l=<>;print $f,sort@l;last' file.txt
오옷!! 이거 그럴 듯 하다!! 더 꼬아보자!!
 perl -ne'@l=<>;last}{print $_,sort@l' file.txt
매우 맘에 드는 코드가 나왔지만, 펄을 새로 시작하는 사람에게는 절대 보여줘선 안될 코드 같다.


오늘의 새로운 아이디어!!

1.  파일을 읽어서 배열에 넣는 방법
perl -ne'@L=($_,<>)' file.txt


2. perl -ne에서  END{}를 쓰기 귀찮다면 }{를 쓰면 된다.
perl -ne'push @L,$_ }{ print sort $L'




2007. 12. 11. 03:01

코드골프 grid-computing

새로운 코드골프 문제가 나왔습니다.
http://codegolf.com/grid-computing
http://kldp.org/node/89102

문제의 내용은 다음고 같은 2자리 숫자로 이루어진 10x10 테이블을 받아서


01 34 46 31 55 21 16 88 87 87
32 40 82 40 43 96 08 82 41 86
30 16 24 18 04 54 65 96 38 48
32 00 99 90 24 75 89 41 04 01
11 80 31 83 08 93 37 96 27 64
09 81 28 41 48 23 68 55 86 72
64 61 14 55 33 39 40 18 57 59
49 34 50 81 85 12 22 54 80 76
18 45 50 26 81 95 25 14 46 75
22 52 37 50 37 40 16 71 52 17

가로 세로 합(총 20개) 중에 최대값을 출력하는 것.

예전에도 몇번 코드골프문제를 풀어본 적이 있지만 순위권에 들기가 너무 힘들어서 좌절 한 적이 있었는데
이 문제는 나온지 얼마 안되기 때문에 이때다 하고 달려들었습니다.
다행히 53글자로 순위권에 안착~~.
시간이 지나면 밀려나겠지만 일단 4위에서 캡춰!! 현재는 6위 -_-;;;;

코드를 공개하고 싶어서 입이 아니 손이 근질근질 거리지만 혹시라도 이 포스트를 읽으실 분의 즐거움을 위해서 당분간 공개하지 않기로 합니다.  비공개 포스트라도 만들어서 임금님 귀는 당나귀 귀라도 외쳐야 겠네요.
2007. 12. 11. 02:39

여러파일을 sorting 하기

갑자기 몇개 파일을 소트해야 할 일이 생겨서

하나의 파일을 sort 하는 방법

perl -i.bak -ne'push@L,$_;END{print sort @L;}' filename

여러 파일을 sort하려면

perl -i.bak -ne'push@L,$_;if(eof){print sort@L;@L=();}' file1 file2 file3

또는

for file in file1 file2 file3;do perl -i.bak -ne'push@L,$_;END{print sort@L;}' $file;done

더 좋은 방법은 당장 생각이 안난다.

find를 이용해서 만든 리스트들이 소트되어 있지 않아서 만든 것인데 실제로는 필요없는 디렉토리가 몇개 들어가 있었다. 필요없는 디렉토리들의 공통점은 숫자로 끝나지 않는다는 것이 었기 때문에 간단히

perl -i.bak -ne'/\d$/ or next;push@L,$_;eof and print sort@L and @L=();' input*10k.txt

다시 생각해 보니 펄을 안쓰는게 더 간단하다
for x in input*10k;do grep -v '[0-9]$' $x | sort > $x.tmp;mv $x.tmp $x;done;

이런....
뭐.. 더 빠르겠지 ㅎㅎ
2007. 11. 27. 22:11

새로운 웹RSS리더 웹피쉬

나의 기본 RSS리더는 Google Reader이다. 몇몇 rss프로그램도 써봤지만 웹RSS리더의 접근성을 포기하게 만드는 프로그램은 보지 못했다. 한RSS리더도 써봤지만 직관성이나 속도가 Google Reader이 더 빠르게 느껴졌기 때문에 현재는 google reader에 안착해 있다. 물론 내가 gmail을 사용한다는 것도 중요한 이유로 작용했다.

이번에 새로운 웹RSS리더 웹피쉬가 나왔다는 얘기를 듣고 방문해봤다. 간단한 리뷰를 쓰면 커피교환권을 준다는 유혹에 넘어가 잠깐 사용해 보게 되었다.
길게 사용해볼 것도 없이 나의 판단은 내려졌다.
화면은 수려하고 기능은 우수하다 그러나 네비게이션이 불편하다.
최근 web2.0의 경향을 따라 매우 다양한 기능과 아름다운 화면을 가지고 있다. 클릭을 하지 않아도 팝업 메뉴가 뜨기 때문에 클릭 횟수를 줄일 수도 있다.
그러나 결정적으로 구글리더에 비해 네비게이션이 불편하다. 글을 읽으면서 구글리더에서 j,k나 방향키를 이용해 글 사이를 이동하던 것이 그리워진다. 무엇보다 직관적이지 않다. 제목을 클릭해서 글을 펼치는 것이라는 것은 쉽게 알 수 있었는데 이 후에 어떻게 접어야 할지 모르겠다.  물론 베타이기 때문에  차후에 보다 사용자 편의가 고려될것이다. 지금의 디자인과 기능에 사용자 편의성이 고려된다면 충분히 매력적인 웹RSS가 될것이다. 물론 아직 나는 구글 리더가 좋다.

'Web' 카테고리의 다른 글

Slide.com  (0) 2007.11.04
2007. 11. 19. 13:53

map, grep 그리고 //g의 함정

문제는 펄스터디 모임중 다음 코드에서 시작되었다.
#!/usr/bin/perl
@str = qw(test test1 test28 test88 test102 test9209);
@grep_ret = grep m/test[0-9]{2}/g, @str;
print("grep_ret : @grep_ret\n");

@str = qw(test test1 test28 test88 test102 test9209);
@map_ret = map m/test[0-9]{2}/g, @str;
print("map_ret : @map_ret\n");
결과 :
grep_ret : test28 test88 test102 test9209
map_ret : test28 test88 test10 test92


이 코드는  map과 grep의 차이를 잘 보여주는 코드이다. 그런데 문제는 두번째 @str을 주석처리 하자 map의 결과가 사라졌다는 것이다.
#!/usr/bin/perl
@str = qw(test test1 test28 test88 test102 test9209);
@grep_ret = grep m/test[0-9]{2}/g, @str;
print("grep_ret : @grep_ret\n");
#@str = qw(test test1 test28 test88 test102 test9209);
@map_ret = map m/test[0-9]{2}/g, @str;
print("map_ret : @map_ret\n");
결과 :
grep_ret : test28 test88 test102 test9209
map_ret :
처음에는 매우 의아한 결과라고 생각했지만 찬찬히 살펴보자 //g의 문제라는 것을 알았다. 첫 grep 에서 g에의해서  매치 포지션이 뒤로 이동해 버린 것이 문제였다.  이를 증명 및 해결하기 위해서 다음 코드를 사용했다.

#!/usr/bin/perl
@str = qw(test test1 test28 test88 test102 test9209);
@grep_ret = grep m/test[0-9]{2}/g, @str;
print("grep_ret : @grep_ret\n");
map{pos=0}@str;
@map_ret = map m/test[0-9]{2}/g, @str;
print("map_ret : @map_ret\n");
결과 :
grep_ret : test28 test88 test102 test9209
map_ret : test28 test88 test10 test92
pos를 이용해서 매치 포지션을 0으로 바꾸자 우리가 원하던대로 코드가 작동했다.
이에 대해 몇가지 얘기들이 있었고 본인이 잘못알고 있던 것을 아는 척하다가(grep에서 반환값이 리스트라는. 엉터리 정보를 주장했다.) grep과 map의 순서를 바꾸자 더 황당한 일이 벌어졌다.
#!/usr/bin/perl
@str = qw(test test1 test28 test88 test102 test9209);
        @map_ret = map m/test[0-9]{2}/g, @str;
print("map_ret : @map_ret\n");
  @grep_ret = grep m/test[0-9]{2}/g, @str;
 print("grep_ret : @grep_ret\n");
 @map_ret = map m/test[0-9]{2}/g, @str;
 print("map_ret : @map_ret\n");
결과 :
map_ret : test28 test88 test10 test92
grep_ret : test28 test88 test102 test9209
map_ret :
이럴수가, 왜 map은 grep에 영향을 주지 않았는데 grep는 map에 영향을 주는 걸까.

이제 문제를 일으킨 //g와 map, grep의 특성들을 자세히 살펴보자.
//g 는 하나의 문자열에 대해서 여러번(global) 매치를 실행하기 때문에 매치가 이루어질때마다 매치가 이루어진 다음의 위치를 메모리에 저장한다. 이 위치는 pos함수로 확인할 수 있고 또 pos에 값을 대입해서 이 위치를 수정할 수 있다. 그런데 매치를 다 찾아서 더이상 매치가 없는 문자열에 다사  //g를 적용하면 어떻게 될까. 예를 통해 확인해보자.
#!/usr/bin/perl
use strict;
my $str="test12test34";
my $count;
$count = $str=~/test/g; print $count, "\t", pos $str, "\n";
$count = $str=~/test/g; print $count, "\t", pos $str, "\n";
$count = $str=~/test/g; print $count, "\t", pos $str, "\n";
$count = $str=~/test/g; print $count, "\t", pos $str, "\n";

결과:
1       4          # 매치가 되었다는 뜻의 1과 다음 매치위치인 "1"의 위치 4가 출력되었다.
1       10        # 마찬가지로 1과 다음 매치위치인 "3"의 위치인 10이 출력되었다.
                    # 더이상 매치할 것이 없기때문에 실패의 의미인  undef가 출력되었고 pos역시 undef.
1       4          # 바로 이거다. 한번더 //g가 호출되면 처음부터 다시 매치를 시작한다.

//g를 리스트에 저장하면 어떻게 될까.
#!/usr/bin/perl
use strict;
my $str="test12test34";
my @result;
@result = $str=~/test/g; print @result, "\t", pos $str, "\n";
@result = $str=~/test/g; print @result, "\t", pos $str, "\n";

결과
testtest
testtest

//g는 모든 매치를 실행해서 매치된 내용을 @list에 집어넣었고 매치가 모두 이루어졌기 때문에 pos는 undef를 반환했다. 앞의 결과와 비슷하게  pos가 undef가 된후 다시 매치를 실행하자 처음부터 매치가 이루어진다.
그렇다면 앞의 코드를 다시 인용해 모든 문제를 짚어보자.

#!/usr/bin/perl
@str = qw(test test1 test28 test88 test102 test9209);
        @map_ret = map m/test[0-9]{2}/g, @str;
print("map_ret : @map_ret\n");
  @grep_ret = grep m/test[0-9]{2}/g, @str;
 print("grep_ret : @grep_ret\n");
 @map_ret = map m/test[0-9]{2}/g, @str;
 print("map_ret : @map_ret\n");
결과 :
map_ret : test28 test88 test10 test92
grep_ret : test28 test88 test102 test9209
map_ret :
첫번째  map에서 map은 list를 반환한다. 따라서 //g는 리스트 컨텍스트로 작동하고 모든 매치된 내용을 리턴 한 후에 매치 포지션을 초기화 시킨다. 따라서 grep은 아무 문제없이 작동한다. 하지만 grep은 스칼라 데이터를 반환하기 때문에 매치 위치를 뒤로 옮겨버립니다.(사실 이말은 틀린 말이네요. grep의 반환값이 아니라 grep이 입력된 리스트 요소들에 대해서  True/False를  판단하기 위해서  마지막  expression의  스칼라 값을  사용한다는 것이 맞겠지요. 예를 들어 극단적으로 grep{(1,2,3,0)}@InputLIst 의 경우에 첫번째 스터디에서 공부했던 것 처럼 (1,2,3,0) 의 마지막 값인 0을 사용해 모두 False라고 판단하게 됩니다.) 따라서 마지막 map에서는 이동된 매치 포지션을 가지고 매치를 실행하게 되고 더이상 매치 할 것이 없으므로 undef만 줄기차게 반환하게 되겠지요. 다음 예제를 보면 좀더 분명해 지리라 봅니다. 매치의 정규표현식과 데이터를 살짝 바꿔봤습니다.
#!/usr/bin/perl
@str = qw(1and2 3and4and5 6 7 8 9 nodigit);
        @map_ret = map m/\d/g, @str;
print("map_ret : @map_ret\n");
  @grep_ret = grep m/\d/g, @str;
 print("grep_ret : @grep_ret\n");
 @map_ret = map m/\d/g, @str;
 print("map_ret : @map_ret\n");
결과 :
map_ret : 1 2 3 4 5 6 7 8 9
grep_ret : 1and2 3and4and5 6 7 8 9
map_ret : 2 4 5
두번째 grep에서 매치 위치를 옮긴 후에도 매치될 내용이 남아 있는 요소 에 대해서는 마지막 map에서 모두 매치해서 반환해 버립니다.

몇가지 요소가 복합적으로 얽혀있는데다가 쭈루룩 쓴 글이라 좀 복잡하네요.
요약하자면
1. //g는 매치가 이루어질때마다 다음 매치를 위해 매치위치를 옮긴다.
2. 매치 위치는 pos를 이용해 알아내거나 수정할 수 있다.
3. 스칼라문맥에서 //g는 호출될때마다 매치성공여부를 반환하고 매치위치를 옮긴다. 매치가 다 이루어진 후에는 //g가 한번더 호출되면 undef를 반환하고 매치 위치를 undef로 설정한다(매치 위치가 문자열의 처음으로 재설정 되는 것과 같은 효과). 따라서 다음 //g 는 문자열의 처음부터 다시 시작된다.
4. 리스트 문맥에서 //g는 가능한 모든 매치를 실행하여 매치된 값들의 리스트를 반환한다. 그리고 매치 위치도 undef로 바꾼다. 따라서 리스트 문맥 이후에 //g는 문자열의 처음부터 매치를 시작한다.
5. grep에서 //g 스칼라 문맥이고 map에서 //g는 리스트 문맥이다. 따라서 grep에서는 매치 위치가 바뀌에 되고 map이후에는 매치위치가 문자열의 처음이 된다.

끝입니다.^^

---
글을 올리고 나서 너무 미진한 부분이 많이 보여서 수정및 추가를 해야하나 하고 고민하고 있었는데 마침 aero님께서 제 고민을 한방에 날려주셨습니다. 감사. 역시 고수의 글은 무섭군요!!





'PerlMania' 카테고리의 다른 글

3번째 펄마니아 스터디 모임  (5) 2007.11.18
펄마니아 스터디 후기  (9) 2007.11.04
2007. 11. 18. 16:35

3번째 펄마니아 스터디 모임

이번주 스터디도 연대에서 있었습니다. 아침부터 지갑을 잃어버리는 등의 악재가 겹쳐서 4시에 딱 맞춰 가는 바람에 범규가 혼자 고생이 많았네요.
예상대로(?) 뜨거운 스터디 시간이었습니다. 4시 30분경에 시작해서 9시 30분까지 5분쉬고 다섯 시간을... 술자리를 위해서 말리고 싶은 마음도 있었지만 발표하시는 분들의 열기에 말도 꺼낼 수가 없었습니다.(사실은 저의 소심함이 가장 큰 원인이었죠.)
지난 시간부터 문제가 되었던 grep,map 문제는 제가 정확히 모르고 떠벌이다가 창피를 당하기도 했습니다.
그러나 기대하시라.. 해결했습니다. 관련 포스트를 따로 올리기로 하지요. 포인트는  grep의 반환값은 스칼라이고 map의 반환값은 리스트라는 것입니다.

스터디가 끝나고 지지난 주부터  계획만하던 "스터디 회원 사진찍기"를 마침내 실행에 옮겼습니다.
신비주의를 원하시는 분들이 있을까봐 걱정했었는데 다행히 모두들 찬성하시더군요.
아쉽게도 이번에 참석하지 못하신 혁진님과 성일님(맞나요?)께서는 다음주를 기약하셔야 겠습니다.
사진은 왼쪽 위에 키가 제일 크신 분부터 시계방향으로 박민영님, 황찬님(고기스님), 이성찬님, 김범규님(bkkim), 임도형님, 저 장범수(pung96), 정현기님(simryang), 김대호님, 김도형님(keedi) 입니다.
임도형님은 이번에 처음 참석하셨는데 내공이 남다르시더군요. 특히 사근사근 설명해 주시는것이 전직이 의심스워지네요(선생님?^^).
사용자 삽입 이미지

펄마니아 스터디 사진


아쉽게도 너무 늦게 끝난데다가 다들 급한 일이 있으셔서 뒷풀이는 저, 김도형님, 김대호님, 이성찬님, 황찬님 이렇게 5명이 진행했습니다. 주종목은.. 역시 제가 좋아하는 삼겹살에 소주였습니다. 도형님은 자전거를 타고 오신 관계로 맥주만 드셨습니다. 막판에 결심을 바꾸시고 소주로 바꾸시려고 했는데 제가 술취하면 말이 많아지는 관계로 이런 저런 얘기에 열을 올리느라 신경을 못써드려서 그냥 맥주만 드셨네요.
무사히 보내 드려서 죄송합니다.
다음번에는 꼭 소주를 열심히 권해드리겠습니다.용인까지 자전거 타고 가신다던데..  대단하십니다.
저는 다른 모임이 있어서 2차를 갔다가 너무 취해 버리는 바람에 쓰러지기 일보직전에 가방을 움켜쥐고 인사도 없이 집으로 뛰어갔다가 선배들에게 부지런히 욕먹는 중입니다.
다들 수고하셨습니다.

'PerlMania' 카테고리의 다른 글

map, grep 그리고 //g의 함정  (3) 2007.11.19
펄마니아 스터디 후기  (9) 2007.11.04