bash에서 파일 이름의 일부인 숫자를 변수로 저장하는 방법

bash에서 파일 이름의 일부인 숫자를 변수로 저장하는 방법

루프를 통해 한 번에 여러 파일을 변경하고 이름을 바꿀 수 있도록 파일 이름의 일부인 숫자를 변수로 저장하려고 합니다. 파일 이름은 Trimmed-barcode*.1.fastq.gz입니다. 여기서 *는 변수 두 자리 또는 세 자리 숫자이고 이를 num으로 저장하려고 합니다. 이를 통해 $num에 앞서 정의한 $number 변수를 곱하고 곱해진 숫자로 각 파일의 이름을 바꿀 수 있습니다(그러나 지금은 echo로 테스트하고 있습니다). 파일 이름에 두 자리 또는 세 자리 숫자를 저장하는 방법은 무엇입니까?

for infile in trimmed-barcode*.1.fastq.gz
  do num= #how do I get this number
  num2=$(($num * $number))
  echo "trimmed-barcode${num2}.1.fastq.gz"
  done

답변1

스크립트를 사용하면 bash문자열에서 두 개의 숫자를 추출할 수 있습니다. 예를 들어

var="abcdefg"
echo "${var:3:2}"    # Outputs "de"

이를 통해 스크립트를 다음과 같이 조정할 수 있습니다.

#!/bin/bash
for infile in trimmed-barcode??.1.fastq.gz
do
    num="${infile:15:2}"    # Two characters starting at position 15
    result=$(( ${num#0} * number ))
    echo "trimmed-barcode$result.1.fastq.gz"
done

$num를 곱할 때 $number값에서 앞에 오는 0을 제거하여 bash8진수로 처리하지 않도록 해야 합니다. 그게 다야 ${num#0}.


두 가지를 모두 요청하도록 질문을 수정했습니다.아니면 셋숫자. 이는 구현을 크게 변경합니다.

  1. 루프를 반복할 수 있지만 이번에는 세 개의 숫자가 일치합니다.

    for infile in trimmed-barcode??.1.fastq.gz
    do
        # Code as above for two digit extracts
    done
    
    for infile in trimmed-barcode???.1.fastq.gz
    do
        # Modify code as above to process three digit values
    done
    
  2. 남은 것이 관심 있는 값이어야 한다고 가정하고 변경되지 않는 부분을 제거하도록 코드를 변경할 수 있습니다.

    for infile in trimmed-barcode*.1.fastq.gz
    do
        num=${infile#trimmed-barcode}    # Strip leading text
        num=${num%.1.fastq.gz}           # Strip trailing text
        result=$(( ${num#0} * number ))
        echo "trimmed-barcode$result.1.fastq.gz"
    done
    

답변2

for file in trimmed-barcode*.1.fastq.gz; do
    x=${file#trimmed-barcode}
    num=${x%.1.fastq.gz}
    echo "$file: $num"
done

또는 Bash에서는 정규식 일치를 사용하여 파일 이름의 원하는 부분을 선택할 수 있습니다.

for file in trimmed-barcode??.1.fastq.gz; do
    [[ $file =~ trimmed-barcode(.*)\.1\.fastq\.gz ]]
    num=${BASH_REMATCH[1]};
    echo "$file: $num"
done

또는 잘라내려면 첫 번째 지점 앞의 두 문자를 선택하면 됩니다 [[ $file =~ (..)\. ]].

답변3

파일 이름의 두 자리를 루프의 변수로 저장하려면 bash에서 파일 이름 확장 및 문자열 조작을 사용할 수 있습니다. 예는 다음과 같습니다.

for infile in trimmed-barcode*.1.fastq.gz
do
  num="${infile:14:2}"
  num2=$((num * number))
  echo "trimmed-barcode${num2}.1.fastq.gz"
done

이 코드에서는 ${infile:14:2} 문자열 확장을 사용하여 파일 이름에서 인덱스 14에서 시작하는 두 자리를 추출합니다. 그런 다음 이 숫자(num)에 $number 변수를 곱하고 결과가 숫자 2에 저장됩니다. 마지막으로 생성된 파일 이름을 수정된 번호로 에코합니다.

파일 이름에 있는 숫자의 실제 위치(이 경우 14)를 기준으로 색인을 조정해야 합니다.

답변4

다음은 Perl rename유틸리티를 사용합니다:

참고: Perl은 배포판에 따라 , , 또는 rename라고도 합니다 . 기능과 명령줄 옵션이 완전히 다르고 호환되지 않는 유틸리티와 혼동 하지 마십시오. Perl 이름 바꾸기를 사용하면 임의로 복잡한 Perl 코드를 사용하여 파일 이름을 바꿀 수 있지만 파일 이름에 대해 간단한 sed와 유사한 s/search/replace/ 작업을 수행하는 데 가장 일반적으로 사용됩니다.file-renameperl-renameprenamerenameutil-linux

먼저 테스트할 파일 이름을 만듭니다.

for i in 11 234 56 789 ; do touch "trimmed-barcode$i.1.fastq.gz" ; done

그런 다음 이름을 바꿉니다.

export number=2
rename -n 's/^(trimmed-barcode)(\d{2,3})(\.1\.fastq\.gz)$/$1 . $2 * $ENV{number} . $3/e' trimmed*

예제 출력:

rename(trimmed-barcode11.1.fastq.gz, trimmed-barcode22.1.fastq.gz)
rename(trimmed-barcode234.1.fastq.gz, trimmed-barcode468.1.fastq.gz)
rename(trimmed-barcode56.1.fastq.gz, trimmed-barcode112.1.fastq.gz)
rename(trimmed-barcode789.1.fastq.gz, trimmed-barcode1578.1.fastq.gz)

-n옵션을 사용하면 시험 실행되므로 내용만 표시됩니다.회의하다. 실제로 파일 이름을 바꾸려면 해당 -n파일을 삭제하거나 -v자세한 출력으로 바꾸십시오.

스크립트가 해시를 통해 변수에 액세스할 수 있도록 변수 $number를 환경으로 내보내야 합니다 . 또는 동일한 명령줄에서 변수를 할당하거나(예를 들어 해당 명령에 대한 변수를 일시적으로 내보내는 효과가 있음) 스크립트에 하드코딩할 수 있습니다.rename%ENVnumber=2 rename -n '...' trimmed*

앞에 있는 숫자(예: 하나 이상의 숫자)에 대해 작동하게 하려면 로 .1.fastq.gz변경하세요 .\d{2,3}\d+

번호 앞의 파일 이름 접두사("트림 바코드"뿐만 아니라)와 첫 번째 번호 뒤의 확장자에 대해 작동하게 하려면 다음 .과 같이 변경하세요.

rename -n 's/(.*?)(\d{2,3})(\..*)/$1 . $2 * $ENV{number} . $3/e' trimmed*

/e이 스크립트는 정규식 수정자를 사용하여 대체 연산자의 오른쪽(교체)에서 Perl 코드를 실행하는 Perl의 기능을 활용합니다 s///. 이 경우 .Perl의 문자열 연결 연산자이므로 코드는 첫 번째 캡처링 그룹( $1)을 두 번째 캡처링 그룹( )에 환경 변수를 $2곱한 다음 세 번째 캡처링 그룹( )과 연결합니다.$number$3

참고로 Perl은 / 옵션을 rename사용하여 강제로 실행하지 않는 한 기존 파일을 덮어쓰지 않습니다 .-f--force

대체 연산자의 왼쪽(검색) 부분에 있는 정규식과 일치하지 않는 파일 이름은 어떤 방식으로든 이름이 바뀌거나 수정되지 않습니다.

관련 정보