특정 비율의 행에 특정 문자열이 포함된 경우 파일을 이동하기 위한 쉘 스크립트

특정 비율의 행에 특정 문자열이 포함된 경우 파일을 이동하기 위한 쉘 스크립트

특정 비율의 줄에 특정 문자열이 포함된 경우 파일을 이동하는 쉘 스크립트를 작성 중입니다.

내 디렉토리에는 약 2000개의 파일이 있으며 각 파일에는 데이터 열이 포함되어 있습니다. 각 파일의 줄 수는 다양합니다. 첫 번째 줄은 제목이고, 다른 줄에는 0보다 큰 숫자가 포함되며 소수점 이하 6자리까지 정확합니다. 전임자:

OMEGA
0.000010
0.000010
0.042214
0.042214
0.042214
0.042214
1.147412

행의 10% 이상이 1보다 큰 값을 포함하는 모든 파일에 관심이 있습니다. 나는 "1"을 포함하는 행의 비율을 사용합니다. "."로 - 하지만 구문에 문제가 있습니다. ".omega"는 내가 관심 있는 파일의 확장자입니다.

이것이 내가 가진 것입니다:

for file in *.omega
do
 if [ $(($(grep '1.' $file | wc -l) / $(grep '.' $file | wc -l)) * 100) -ge 10 ]; then
 mv $file positive_COGs/ 
 fi
done

나는 성공하지 못한 채 브래킷/브래킷 배치를 시도했습니다. 또한 - "-ge"를 사용하여 %(정수 아님)를 정수 "10"(?)과 비교하는 것이 적절한지 잘 모르겠습니다.

어떤 조언이라도 대단히 감사하겠습니다. bash를 사용하여 스크립트를 실행하고 있습니다.

건배!

답변1

문제는 bash가 정수 연산을 수행하므로 20/50을 취하면 항상 0이라는 것입니다. 따라서 테스트 횟수 > 1을 행 수로 나눈 값은 0이고, 0 * 100은 0이며 항상 10보다 작습니다.

나누기 전에 100을 곱하면 원하는 결과가 나올 것 같아요.

답변2

최신 버전의 GNU 4.x를 사용하면 awk다음을 수행할 수 있습니다.

awk '
  BEGINFILE { count = 0 }
  FNR == 1  { next }
  $1 > 1.0  { count++ }
  ENDFILE   { if (count/(FNR-1) >= 0.1) printf "mv %s positive_COGs\n", FILENAME }
' *.omega | sh

카운터를 초기화하고( BEGINFILE), 헤더 라인을 건너뛰고( FNR == 1), 데이터 파일에서 찾은 숫자를 기준으로 계산하고, ENDFILE조건에 일치하는 파일(또는 셸 명령)을 인쇄합니다( ). 그런 다음 mv셸에 명령을 입력하여 이동을 수행합니다.

답변3

/정수 나누기는 산술 표현식에서 수행됩니다. 즉, 몫 연산자입니다. 대부분의 쉘은 부동 소수점 연산이 아닌 정수 연산만 수행할 수 있습니다.

합계로 나눈 다음 100을 곱하는 대신 그 반대를 수행하십시오. 이렇게 하면 grep … | wc -l단순화됩니다 grep -c.

게다가, 는 틀렸습니다. grep '1.'a 다음에 다른 문자가 오는 모든 줄을 선택합니다. 즉, 줄의 맨 끝이 아닌 a가 포함된 줄을 선택합니다. 10 사이의 번호가 매겨진 행을 선택하세요.11케이+ 1과 10케이+ 2인 경우 를 사용합니다 grep '1\.'. 1보다 큰 숫자가 포함된 행을 선택하려면 를 사용합니다 grep '[1-9][0-9]*\.'.

비어 grep .있지 않은 행이 선택됩니다. 모든 행을 선택하려면 를 사용하십시오 wc -l. 숫자가 있는 행만 선택하려면 다음과 같이 사용하세요 grep '[0-9]'(여기에는 숫자만 있는 행뿐만 아니라 모든 곳에 숫자가 있는 행이 포함됩니다).

if [ $(($(grep -c '[1-9][0-9]\.' <"$file") * 100 / $(grep -c '[0-9]' <"$file"))) -ge 10 ]; then

파일을 한 번만 처리하고 발생하는 숫자를 계산하는 것이 더 빠르고 강력할 수 있습니다. 이를 위해 awk를 사용할 수 있습니다.

if awk '
    $0 >= 1 {good += 1}
    $0 != 0 || $0 ~ /^ *0*\.0*$/ {total += 1}
    END {if (good < total/10) exit(1)}
'; then

관련 정보