2016-09-20 8 views
3

이것은 다음을 기반으로 한 새로운 질문입니다. Output the result of each loop in different columns.리눅스에서 루프의 문자열에서 특정 문자 추출

하지만 새로운 질문이기 때문에 링크에서 질문을 볼 필요는 없으며 아래의 새로운 질문을 명확하게 설명 할 것입니다.

money.txt 파일은 두 개의 열이 있습니다 (이름과 돈을)

Mary 13 
Lucy 8 
Jack 20 

range.txt 파일 세 개의 열이 있습니다 (과일, MIN_VALUE 및 MAX_VALUE)

apple 10 15 
banana 7 12 
orange 17 22 
blueberry 14 22 

내 목표는 돈이 있는지 여부를 테스트하기를 money.txt의 파일은 range.txt에서 min_value와 max_value 사이에 있습니다. 그렇다면 fruit의 (max_value - money) 번째 문자를 range.txt에 인쇄하고, 그렇지 않으면 "x"을 출력하십시오. 예를 들어

, Mary13apple의 MIN_VALUE 및 MAX_VALUE 내에 상기 money.txt13이고 max_value-money 값은 15이고 - = 213, 그래서 apple의 두번째 문자를 출력한다, 즉 p.

예상 된 결과는 다음과 같습니다 (제 4 열은 메리입니다, 5 열은 루시를 위해, 그리고 6 번째 열은 잭입니다) @ocurran의 도움으로

apple 10 15 p x x 
banana 7 12 x a x 
orange 17 22 x x r 
blueberry 14 22 x x l 

, 나는 시도 :

awk: line 14: syntax error at or near { 
awk: line 16: syntax error at or near else 
awk: line 19: syntax error at or near } 

fruitcharacter=${fruit:($3-money[i]-1):1}가 작동하지 않을 수있는 것 같다

# load prices by index to maintain read order 
awk 'FNR == NR { 
    money[names++]=$2 
    next 
} 
# save max index to avoid using non-standard length(array) 
END { 
    names=NR 
} 
{ 
l = $1 " " $2 " " $3 
for (i=0; i < names; i++) { 
    if ($2 <= money[i] && $3 >= money[i]) { 
      fruit=$1 
      fruitcharacter=${fruit:($3-money[i]-1):1} 
      l = l " " $fruitcharacter 
    } else { 
      l = l " x" 
    } 
} 
print l 
}' money.txt range.txt 

결과 는 것을 보여 주었다. 그러나 내가 알고 있듯이 ${string: index: length}을 사용하여 문자열의 문자를 추출 할 수 있으며, 왜이 상황에서 작동하지 않는지 알 수 없습니다. 이 문제를 해결하도록 도와 주시겠습니까? 고맙습니다.

+1

awk 스크립트의 시작에서 14 줄을 카운트하면 awk에 대한 구문 넌센스 인'fruitaracter = $ {fruit : ($ 3-money [i] -1) : 1}'행을 얻습니다. 문법 에러 출력 메세지 "아시다시피, 우리는 문자열의 문자를 추출하기 위해'$ {string : index : length} '를 사용할 수 있습니다."그러나 그건 사실이 아닙니다. (힌트 : ** awk는 껍데기가 아닙니다! **). Arnold Robbins의 Effective Awk Programming, 4th Edition을 읽어보십시오. –

+1

@ Edmonton 감사합니다. 나는 몇 가지 개념을 혼합한다. – lightsnail

답변

4
$ cat tst.awk 
NR==FNR { money[NR]=$2; next } 
{ 
    out = $0 
    for (i=1; i in money; i++) { 
     out = out OFS ((money[i]>=$2) && (money[i]<=$3) ? substr($1,2,1) : "x") 
    } 
    print out 
} 

$ awk -f tst.awk money.txt range.txt 
apple 10 15 p x x 
banana 7 12 x a x 
orange 17 22 x x r 
blueberry 14 22 x x l 

당신은 약간의 열 머리글과 더 좋은 출력 서식을 원하는 경우 :

$ cat tst.awk 
NR==FNR { names[NR]=$1; money[NR]=$2; next } 
FNR==1 { 
    out = "Fruit" OFS "Min" OFS "Max" 
    for (i=1; i in names; i++) { 
     out = out OFS names[i] 
    } 
    print out 
} 
{ 
    out = $0 
    for (i=1; i in money; i++) { 
     out = out OFS ((money[i]>=$2) && (money[i]<=$3) ? substr($1,2,1) : "x") 
    } 
    print out 
} 

$ awk -f tst.awk money.txt range.txt | column -t 
Fruit  Min Max Mary Lucy Jack 
apple  10 15 p  x  x 
banana  7 12 x  a  x 
orange  17 22 x  x  r 
blueberry 14 22 x  x  l 
+1

감사합니다. @EdMorton 그러나'substr ($ 1,2,1)'이 무엇을 의미하는지 궁금합니다. 그것은'range.txt'에서'$ 1'의 두 번째 문자를 추출하는 것을 의미합니까? 그렇다면, 기대 한 바가 아니므로'range.txt'에'$ 1'의 (max_value -'money') 번째 문자를 넣고 싶습니다. – lightsnail

+1

네, 그것이 그것이 의미하는 바입니다. 그래서 max_value가'$ 3'에 저장되고 돈이''money [i]' '에 저장된다면,''max_value - money' 문자를 얻기 위해'substr ($ 1,2,1)'에해야 할 일은 무엇이라고 생각합니까? '2' 문자 대신에? 낚시 101에 오신 것을 환영합니다 .--). –

+1

'substr ($ 1, ($ 3-money [i]), 1)'^ _^ – lightsnail

0
나는 개인적으로 이것에 대한 awk를 사용하여 매우 간단는 이럴 유지하지 않을

:

#!/bin/bash 

money=$(<money.txt) 
range=$(<range.txt) 

while read -r fruit min max; do 
    echo -e "$fruit $min $max \c" 
    while read -r name cash; do 
     if (($cash > $min)) && (($cash < $max)); then 
      pos=$(($max - $cash - 1)) 
      echo -e "${fruit:pos:1} \c" 
     else 
      echo -e "x \c" 
     fi 
    done <<< "$money" 
    echo 
done <<< "$range" 

출력을 주어진 소스 데이터에 대해 설명한 것과 동일하며 논리는 다른 데이터에서도 일관되게 작동해야합니다. :)

+0

[왜 - 사용 - 쉘 - 루프 - 프로세스 - 텍스트 - 간주 - 나쁜 - 연습] (http://unix.stackexchange.com/questions/169716/why -is-shell-loop-to-process-text-consider-bad-practice)를 사용하여 awk를 사용해야하는 몇 가지 이유에 대해 알아보십시오. 또한 money.txt를 여러 번 읽으므로 접근 속도가 매우 느릴 것입니다. 관례에 따라 수출되지 않은 변수 이름에 대문자를 사용하지 말고 내장 및 내 보낸 이름과의 충돌을 피하고 일부 스크립트에 수학 연산자'((...))를 사용하고 있으므로 그냥 그리고 나서 모든 것을 명확하고 일관성있게하십시오. –

+0

촬영 포인트, 나는 나쁜 습관을 바로 잡았다. :) 처음에는 테스트 할 때 데이터를 생성하는 데 신경 쓰고 싶지 않았기 때문에 데이터를 변수로 사용했습니다. 마지막으로 방금 OP의 질문과 일치하도록 파일에서 읽도록 변경했습니다. 디스크에서 중복 읽기가 발생한다는 것을 인식하지 못했습니다. –