질문:
다음과 같은 여러 텍스트 파일(.fas)이 있습니다.
파일 1.fas:
>species1
AICGICVIAGIAIYIAAICG
>species2
AICGIVVYICAGAYICAGCG
파일 2.fas:
>species1
AIG
>species2
GCI
내가 관심 있는 것은 두 번째 줄의 문자 수를 계산하는 것입니다(파일이 정렬될 때 파일의 모든 종에 대해 동일함).
내 현재 하나의 라이너 :
for i in *.fas; do echo -n "$i," && grep -m 1 -A 1 '>' $i | tail -n 1 | wc -c; done;
이는 어느 정도 작동하지만 계산된 숫자는 개행 문자를 계산하기 때문에 실제 문자 수보다 한 숫자 더 높습니다. 개행 문자를 제외한 문자만 계산되도록 하려면 어떻게 해야 합니까?
현재 출력:
file1.fas,21
file2.fas,4
원하는 출력:
file1.fas,20
file2.fas,3
답변1
| wc -l
줄 수를 인쇄합니다.| wc -c
줄바꿈을 포함하여 문자 수를 인쇄합니다.| wc -lc
둘 다 인쇄합니다(줄 번호 먼저).
따라서 간단히 뺄 수 있습니다. (대신 작성하세요 |wc -c
)
| wc -lc | awk '{print $2 - $1}'
한 줄에만 시퀀스를 인쇄하는 경우 개행 수 대신 1을 뺄 수 있습니다.
또는 awk
전체 줄을 일치시키고 해당 문자 수를 계산하여 사용할 수 있습니다.
| awk '{match("[A-Z]*");print RLENGTH}'
RLENGTH
경기의 길이입니다(여기서는 전체 라인). 여기서는 대문자만 사용한다고 가정합니다 . 그렇지 않으면 .
대신 .[A-Z]
vim
(텍스트 편집기이므로 스크립트와 호환되지 않을 수 있음) 에서 범위(하나 이상의 줄)를 시각적으로 선택하고 다음을 실행합니다.
:'<,'>s/[A-Z]*//gn
다음을 사용하여 개행 문자를 제거할 수도 있습니다 tr
(여러 줄에서도 작동).
| tr -d '\n' | wc -c
그건 그렇고, 이를 수행하는 다른 방법이 많이 있을 것입니다.
답변2
.fas 파일을 찾는 데 사용되는 find
find 명령은 마치 awk가 해당 파일을 한 번에 처리할 수 있는 것처럼 해당 파일을 awk의 명령줄에 푸시합니다. 따라서 awk 호출 수가 최소화됩니다.
$ find . -maxdepth 1 -type f -name '*.fas' -exec \
awk -v OFS=, 'FNR==2{print FILENAME, length();nextfile}' {} +
산출:
./file1.fas,20
./file2.fas,3
답변3
다음 perl 한 줄 명령을 사용하여 파일 이름과 두 번째 줄의 길이(쉼표로 구분)를 인쇄합니다. 개행 문자를 제거하려면 플래그를 사용하세요 -l
.
for i in *.fas; do perl -lne 'if ( $. == 2) { print join ",", $ARGV, length $_; last LINE; }' $i ; done
입력하다:
cat > file1.fas <<EOF
>species1
AICGICVIAGIAIYIAAICG
>species2
AICGIVVYICAGAYICAGCG
EOF
cat > file2.fas <<EOF
>species1
AIG
>species2
GCI
EOF
산출:
file1.fas,20
file2.fas,3
Perl 단일 라이너는 다음과 같은 명령줄 플래그를 사용합니다. :
-e
: Perl에게 파일이 아닌 인라인 코드를 찾도록 지시합니다.
-n
: 한 번에 한 줄씩 입력을 반복하며 $_
기본적으로 할당됩니다. : 코드 인라인을 실행하기 전에 입력 줄 구분 기호(*NIX의 기본값)를 제거
-l
하고 인쇄할 때 추가합니다."\n"
$ARGV
현재 입력 파일의 이름입니다. 는 입력 라인 번호 2( )
length $_
로 선택된 현재 라인의 길이입니다 . 속도를 향상시키기 위해 줄 길이를 인쇄한 후 코드가 마지막 입력 줄로 점프하도록 합니다.$. == 2
last LINE
또한보십시오: