awk 또는 sed를 사용하여 열 내에서 산술 연산 수행

awk 또는 sed를 사용하여 열 내에서 산술 연산 수행

산술 결과에 통합하려는 간단한 산술 방정식이 포함된 열이 있는 파일이 있습니다.

입력 샘플(탭으로 구분된 열):

+104-1+12   6   +3

각 열 내의 산술 합계를 계산하고 싶습니다. 열에 산술 기호가 포함되어 있지 않으면 +항목 앞에 가 포함되어 있는 것처럼 처리합니다. +열이 unsigned로 시작하는 경우 sed를 통해 기호를 추가하는 것이 쉬울 지라도 ( sed -E 's/(\t)([0-9]*)/\1\t+\2/g'예제에서처럼 행이 숫자로 시작하지 않는다고 가정하면 작동 가능)

내 예상 결과는 다음과 같습니다.

115 6   3

유닉스에서 어떻게 이를 달성할 수 있나요? awk/sed 솔루션이 선호됩니다.

답변1

당신이 사용할 수있는 perl:

perl -pe 's/[\d+-]+/eval$&/ge' your-file

심지어:

perl -pe 's/[\d+-]+/$&/gee' 파일 (Rakesh에게 감사드립니다)

zsh같은

set -o extendedglob # for the ## operator (same as ERE +)
while IFS= read -r line; do 
  printf '%s\n' ${line//(#m)[0-9+-]##/$((MATCH))}
done < your-file

또는:

zmodload zsh/mapfile
set -o extendedglob
printf %s ${mapfile[your-file]//(#m)[0-9+-]##/$((MATCH))}

-이 네 가지 중에서 우리는 숫자 와 문자 의 시퀀스를 찾고 +이를 인터프리터의 산술 프로세서( evalin perl(또는 ee대체 확장이 perl코드로 평가되도록 하는 플래그), $((...))in zsh)에 전달합니다.

표현식을 인터프리터에 전달하기 전에 유효성을 검사하지 않으므로 오류가 발생할 수 있습니다(예: -+-또는 같은 시퀀스 에서 3++). 그러나 최소한 숫자와 -/ +문자만 고려하므로 보고된 오류보다 더 많은 오류가 발생하지는 않습니다. 메시지를 보내고 명령을 중단합니다.

답변2

반복하지 않겠습니다"sed" 추가대답; awk에서도 방법을 찾지 못했지만 여기에 bash 버전이 있습니다.

while IFS= read -r line
do
  set -f; set -- $line
  for e in "$@"
  do
    printf "%d " "$(( e ))"
  done
  echo
done < input

답변3

sed -E 's/(\t)([0-9])/\1+\2/g' data.file |
while IFS= read -r l; do
   set -f; IFS=$'\t'
   printf '0%s\n' $l | bc -l | paste -s -
done

sed -e 's/\t\([0-9]\)/\t+\1/' data.file |
while IFS= read -r l; do
   set -f; IFS=$'\t'
   printf '0%s\n' $l | bc -c |
   sed -ne '
      $!{
         y/:@irKW/      /
         s/[^ 0-9]/ & /g
         s/[ ][ ]*/ /g;s/^[ ]*//;s/[ ]*$/p/p
      }
   ' | dc | paste -s -
done

여기서는 수학적 표현의 표현을 생성 postfix하고 이를 후위 계산기에 전달하기 전에 dc명령 출력에서 ​​수학적이 아닌 정보를 정리합니다 bc -c.

결과

115     6       3

답변4

다음은 외부 실행 파일을 사용하지 않고 숫자의 문자열 표현을 숫자 표현으로 마샬링하는 awk의 기능을 활용하는 모든 awk 솔루션입니다.

awk -F"\t" \
'BEGIN { OFS="\t" }
 { gsub(/-/,"|-") 
   gsub(/\+/,"|")
   for(i=1; i<=NF; i++) { ## iterate over columns
     num_parts=split($i,parts,"|")
     for(j=1; j<=num_parts; j++) ## iterate over arithmetic expression parts
       sums[i] += parts[j]+0 ## Adding zero marshals the string into a numeric
   }}
 END{
      for(i=1; i<=NF; i++) { 
        if(i>1) printf OFS
        printf sums[i]
      } 
      print "" }' file

관련 정보