중첩된 while 루프

중첩된 while 루프

다음 명령을 사용하여 의 일부 ID를 일치시키고 file 1에 저장된 데이터를 검색합니다 referencefile.

while read -r line; do
    awk -v pattern=$line -v RS=">" '$0 ~ pattern { printf(">%s", $0); }' referencefile;
done <file1 >output

디렉터리에 file1과 유사한 50개의 파일이 저장되어 있고 이 모든 파일에 대해 위 명령을 실행하고 출력을 별도의 파일로 저장하려고 합니다. 하나의 명령(예: 중첩 루프)을 통해 이를 달성할 수 있는 방법이 있습니까?

참조 문서

>LD200FFFFFFFFFFFFFFFFFFFFSSSSSSSSS
 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
 SSSSSSSSSSSSSSS
>LD400HHHHHHHHHHHHHHHHHHHHHHHHHHHHH
 HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
>LD311DDDDDDDDDDDDDDDDDDDDDDDDDDDDD
>LD500TTTTTTTTTTTTTTTTTTTTTTTTTTTTT
>LD100KKKKKKKKKKKKKKKKKKKKKKKKKKKKK

샘플 파일 1

LD100
LD200
LD311

예상 출력 1.txt

>LD100KKKKKKKKKKKKKKKKKKKKKKKKKKKKK
>LD200FFFFFFFFFFFFFFFFFFFFSSSSSSSSS
 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
 SSSSSSSSSSSSSSS
>LD311DDDDDDDDDDDDDDDDDDDDDDDDDDDDD

샘플 파일 2

LD500
LD400

예상 출력 2.txt

>LD500TTTTTTTTTTTTTTTTTTTTTTTTTTTTT
>LD400HHHHHHHHHHHHHHHHHHHHHHHHHHHHH
 HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH

답변1

단일 명령줄을 검색하는 대신 이를 수행하기 위해 스크립트를 사용하고 있다는 것을 이해합니다. 그렇다면 스크립트를 다음과 같이 변경하는 것은 어떻습니까?

#!/bin/bash
Directory="$1"
ls "$Directory" | while read FileName
do
  while read -r line
  do
   awk -v pattern="$line" -v RS=">" '$0 ~ pattern { printf(">%s", $0); }' referencefile;
  done < "$Directory"/"$FileName" > OutputDirectory/"$FileName".out
done

스크립트는 다음과 같이 호출되어야 합니다.

<script> <directory with input files>

사용에 관한 몇 가지 참고사항:

  • 반드시 존재 해야 합니다 OutputDirectory. 스크립트에서 편집하거나 매개변수를 추가하세요.
  • 입력 파일만 포함 되어야 하며 <directory with input files>하위 디렉터리는 포함되어서는 안 됩니다. 그렇지 않으면 오류 메시지가 표시됩니다.

경고하다

스크립트는 구문 분석에 의존합니다 ls. 이렇게 하면 방법을 더 쉽게 이해할 수 있을 만큼 스크립트를 단순하게 유지할 수 있지만 일반적으로권장되지 않음파일 이름의 특수 문자로 인해 바람직하지 않은 동작이 발생할 수 있기 때문입니다. 입력 파일의 이름이 너무 화려하지 않은 간단한 설정에서 작동합니다. 이름에 공백을 넣어도 괜찮지만, 예를 들어 이름에 줄바꿈을 사용하면 오류가 발생하고 해당 파일은 처리되지 않습니다.

답변2

일반적으로 다음과 같이 할 수 있습니다.

for f in file*; do
    while read ...; do
        some commands...
    done < "$f"
done > output

그렇지 않으면

cat file* | while read ...; do
    some commands...
done > output

네가 원한다면오직일치하는 줄이 있으면 파일에서 패턴을 읽고 일치하는 줄을 인쇄하여 grep이 작업을 더 직접적으로 수행할 수 있습니다 .grep -f

for patternfile in file*; do
    grep -f "$patternfile" referencefile
done

답변3

for 루프에서 xargs + grep에 대한 호출을 래핑할 수 있습니다. grep은 참조 파일에 표시된 순서대로 캡처하므로 출력 순서가 file1의 입력과 일치하지 않을 수 있습니다.

for f in file*;do
  < "$f" paste -sd\||\
      xargs -r -I{} grep -Pzo '(?m:(?:^[>](?:'{}')\D.*\n)(?:[^>].*\n)*)' reference.file | tr -d '\0' \
  > "$f.out"
done

관련 정보