![중괄호를 사용해도 연결 문자열에 공백이 삽입되었습니다.](https://linux55.com/image/210126/%EC%A4%91%EA%B4%84%ED%98%B8%EB%A5%BC%20%EC%82%AC%EC%9A%A9%ED%95%B4%EB%8F%84%20%EC%97%B0%EA%B2%B0%20%EB%AC%B8%EC%9E%90%EC%97%B4%EC%97%90%20%EA%B3%B5%EB%B0%B1%EC%9D%B4%20%EC%82%BD%EC%9E%85%EB%90%98%EC%97%88%EC%8A%B5%EB%8B%88%EB%8B%A4..png)
다음 구문을 사용하여 파일 이름을 읽고 확장자를 수정하여 데이터 파일과 일치하는 이름을 생성합니다. 예를 들어 ABC_1.fastq.Blockxy, XYZ_1.fastq.Block34가 있고 ABC_2.fastq.Block12, XYZ_2.fastq.Block34를 새 파일 이름으로 생성하려고 합니다.
for infile in *_1.fastq.Block*
do
#base=$(basename ${infile} _1.fastq.**)
IFS='_'
read -ra ADDR <<< $infile
base=${ADDR[0]}
IFS='.'
read -ra ADDR <<< ${ADDR[1]}
second_file="${base}_2.fastq.${ADDR[2]}"
echo $second_file
done
실행되면 스크립트가 인쇄됩니다.
ABC_2 fastq Block12
XYZ_2 fastq Block34
그것이 fastq와 Block12 사이의 공간입니다. 연결할 때 왜 세 문자열 사이에 마침표 대신 공백이 생기나요? 변수 이름에 중괄호를 사용하면 이 문제가 해결될 것이라고 생각합니다.
답변1
존재하다
echo $second_file
매개변수 확장을 인용하는 것을 잊어버렸기 때문에 이는 분할+글로브의 영향을 받습니다. 따라서 를 사용하면 먼저 , 로 분할되고 IFS=.
각 ABC_2.fastq.Block12
단어 ABC_2
는 글로빙의 영향을 받습니다. 어떤 단어에도 글롭 연산자가 포함되어 있지 않기 때문에 여기서는 효과가 없습니다.fastq
Block12
따라서 3개의 매개변수가 전달 echo
되고 인쇄 공간이 구분됩니다.
변수의 내용과 개행 문자를 인쇄하려면 다음이 필요합니다.
printf '%s\n' "$var"
자세한 내용은 다음을 참조하세요.
이제 코드에 몇 가지 주석을 추가하세요.
zsh
Bash에는 동등한 glob(N)
한정자나 ksh93의 glob 연산자가 없으므로~(N)
for 루프에서 glob을 사용하기 전에 (적어도) 다음 옵션을 설정해야 합니다nullglob
.shopt -s nullglob for infile in *_1.fastq.Block*; do...
이 작업을 수행하지 않고 일치하는 파일이 없으면 텍스트를 반복하게 됩니다.
*_1.fastq.Block*
다음을 통해서만 IFS를 설정할 수 있습니다
read
(이전 버전에 필요한 인용문 참조IFS=_ read -ra ADDR <<< "$infile"
). 이렇게 하면 런타임에만 변경되고 반환 후에는 이전 값으로 되돌아갑니다.$infile
bash
$IFS
read
read
IFS=. read -ra <<< "$var"
나누는 것은 끔찍한 방법입니다. First는 한 줄에 대해서만 작동합니다$var
. 이는 반드시 파일 이름의 경우는 아니며 매우 비효율적입니다. 여기에는 의 내용을$var
임시 파일에 저장하거나 의bash
버전 및/또는 크기에 따라 파이프한$var
다음 개행 문자를 찾을 때까지 한 번에 1바이트씩 읽는 작업이 포함됩니다.여기에서는 대신 분할+글로브 연산자를 사용할 수 있습니다.
IFS=:; set -o noglob addr=( $infile )
addr=( $infile'' )
(또는아니요후행을 무시합니다:
. )또는 적절한 분할 연산자를 사용하여 더 나은 쉘로 전환하십시오.
또 다른 접근 방식은 다음과 같습니다.
regex='^(.*)_1\.fastq\.(Block.*)$' if [[ $infile =~ $regex ]]; then outfile=${BASH_REMATCH[1]}_2.fastq.${BASH_REMATCH[2]} ...
정규식 일치는 유효한 텍스트에서만 작동하며, 이는 다시 파일 이름을 보장하지 않습니다.
여기에서는 표준
sh
파라메트릭 확장 연산자를 사용할 수도 있습니다.new_file=${infile%_1.fastq.Block*}_2.fastq.Block${infile##*_1.fastq.Block}
또는 ksh93 스타일:
new_file=${infile/_1.fastq.Block/_2.fastq.Block}
_1.fastq.Block
(파일 이름이 여러 번 나타나는 경우 이러한 모든 방법 간에 동작에 차이가 있다는 점에 유의하십시오.)
1 그러나 a가 런타임에 trap
처리 되면 read
이 트랩의 코드가 수정됩니다.$IFS