특정 조건에 따라 파일에서 텍스트 추출

특정 조건에 따라 파일에서 텍스트 추출

다음과 같은 기록이 포함된 파일이 있습니다.

434419\Teclu\Tudor\1501\9502
187650\Cosma\Sorin\1504\9253
239474\Teclu\Daniel\1502\5245
844936\Gaman\Mihai\1505\4074
942341\Avram\Tudor\1505\4543
137158\Gaman\Marius\1505\5244
531747\Francu\Daniel\1503\2226
382144\Teclu\Daniel\1501\9943
913409\Gaman\Mihai\1501\5473
901028\Avram\Mihai\1502\6169
382207\Dedu\Alex\1504\5428
726697\Gaman\Sorin\1502\5071
271503\Gaman\Ionut\1505\6643
147791\Dedu\Dragos\1503\4955
495572\Cosma\Alex\1505\9750
769482\Popescu\Sorin\1505\5472
410724\Marin\Mihai\1502\7317
381000\Marin\Daniel\1503\7321
251934\Popescu\Ionut\1504\8288
416161\Gaman\Mihai\1501\8245
523401\Gaman\Mihai\1504\3101
347491\Avram\Daniel\1504\2017
329372\Dedu\Sorin\1502\8528
509554\Popescu\Ionut\1502\7972

\로 구분된 필드. 첫 번째 필드는 ID, 두 번째 필드는 성, 세 번째 필드는 이름, 네 번째 필드는 급여, 다섯 번째 필드는 성과 점수입니다.

하나의 매개변수(즉, 성)를 사용하여 파일의 처음과 마지막 10줄에서 해당 이름을 가진 사람을 찾는 스크립트를 작성해야 합니다. 그런 다음 이 사람들 중에서 급여가 가장 낮은 사람을 선택하거나, 이름과 급여가 같은 사람이 두 명 이상 있으면 성과 점수를 비교하여 점수가 더 높은 사람을 선택합니다. 이 사람의 경우 신분증을 인쇄해야 합니다.

나는 머리와 꼬리 자르기의 조합과 더 많은 명령을 시도했습니다.

{ head -n 10 file.txt ; tail -n 10 file.txt } | grep $NAME | sort -t '\' -r k 4

급여가 낮은 것부터 높은 것 순으로 정렬해 놓았는데, 급여가 같으면 그 다음에는 어떻게 해야 할지 모르겠습니다.

답변1

명령의 시작 부분을 유지하십시오.

{ head -n 10 file.txt ; tail -n 10 file.txt; } |
grep $NAME | sort -t '\' -k 4 -k 5 |
awk -F'\\' '!wage{wage=$4;id=$1;next} wage==$4{id=$1} END{print id}'

이것awk스크립트는 기본적으로 사용자가 제공한 알고리즘에 대한 텍스트 설명을 가져와서 수식에 넣습니다.

물론 파이프라인의 처음 3개 명령을 더 많은 awk 논리로 바꿀 수도 있습니다. 예를 들면 다음과 같습니다.

$ myFun() {
    awk -F'\\' -v s=$2 -v l=`wc -l<$1` '
      $2==s&&(NR<11||NR>l-11)&&(!wage||wage>$4||(wage==$4&&$5>perf)){
        wage=$4; id=$1; perf=$5;
      }
      END{ print id; }' $1; }
$ myFun exampleData.dsv Teclu
382144
$ myFun exampleData.dsv Gaman
416161

주석에서 OP를 참고하십시오: '$1', '$2' 등 awk의 변수는 동일한 이름의 쉘 변수와 독립적입니다.

답변2

TXR 리스프:

(defstruct person ()
  id last first wage score
  (:method equal (me)
    (list (- me.wage) me.score)))

(let* ((surname (pop *args*))
       (database (build (awk (:set fs "\\")     ;; backslash field sep
                             ((fconv i - - i i) ;; int, noconv, noconv, int, int
                              (add (new person
                                        id [f 0] last [f 1] first [f 2]
                                        wage [f 3] score [f 4])))))))
  (del [database 10..-10]) ;; drop all but first/last ten
  (let* ((select-surname (keep-if (op equal @1.last surname) database))
         (best (find-max select-surname)))
    (put-line (if best `best ID: @{best.id}` "notfound"))))

시험:

$ txr process.tl nonexistent data
notfound
$ txr process.tl Teclu data
best ID: 382144
$ txr process.tl Gaman data
best ID: 416161
$ txr process.tl Popescu data
best ID: 509554
$ txr process.tl Francu data
best ID: 531747

(find-max select-surname)간단한 방법, 즉 성으로 필터링된 데이터베이스에 함수를 적용하여 최상의 ID를 찾을 수 있는 이유는 무엇 find-max입니까?동등한 대체 구조에 대해 정의된 메소드 person:

(:method equal (me)
  (list (- me.wage) me.score))

equal이 메소드가 존재하면 less이 유형의 객체가 이상의 값과 비교되거나 :equal-based해시 테이블 등에서 해시될 때 마다 equal객체의 메소드가 호출되고 반환 값이 그 자리에 사용됩니다. 따라서 여기서 우리가 말하는 것은 person마이너스 임금(낮을수록 좋음)과 분수로 구성된 목록을 사용하여 두 항목의 평등을 비교하는 것입니다. 거기에서 목록 동등/부등의 일반 TXR Lisp 의미가 적용됩니다.

1> (greater '(1 1) '(1 0))
t
2> (greater '(1 1) '(1 2))
nil
3> (greater '(2 1) '(1 2))
t

해당하는 첫 번째 요소가 비교되고, 같으면 두 번째 요소가 비교되는 식입니다.

관련 정보