내 입력 파일은 행 길이가 가변적인 단일 열입니다. 내 코드는 이 줄을 계산하고 지정된 숫자를 인쇄해야 합니다. 내가 가진 문제는 변수 "A"에 캡처된 줄 수가 1보다 작은 경우 출력 파일이 비어 있지 않도록 최소한 1줄을 인쇄하고 싶다는 것입니다. "A"(총 행 수의 1%)가 1보다 크면 해당 행 수를 인쇄하고 싶습니다. 내 혼합 awk-bash 코드는 다음과 같습니다.
#!/bin/sh
for i in {1..2}
do
input="../ExpressionSet_"$i"_chunk.txt"
for j in {1..2}
do
A=$(awk 'END{print NR*0.01}' $input)
Y=1
X=0
if (( "$A" -lt "$Y")); then
X=$A+1
else
X=$A
fi
awk 'NR<='$X' {print $0}' $input > "$i"_top1pc.txt
B=$(awk 'END{print NR*0.05}' $input)
awk 'NR<='$B' {print $0}' $input > "$i"_top5pc.txt
혼란스럽게도 다음과 같은 오류 메시지가 계속 나타납니다.
thresholdSelector_pc.sh: line 20: ((: 0.24 -lt 1: syntax error: invalid arithmetic operator (error token is ".24 -lt 1")
thresholdSelector_pc.sh: line 20: ((: 47.24 -lt 1: syntax error: invalid arithmetic operator (error token is ".24 -lt 1")
그런데 inputFile1에는 24줄이 있고 inputFile2에는 4724줄이 있습니다. 도와주셔서 감사합니다!
답변1
귀하의 근본적인 문제는 sh 스크립트에서 bash 구문을 사용하려고 한다는 것입니다. Bash는 sh의 공통 분모에 대한 확장을 정의합니다. bash 특정 기능을 사용하려면 스크립트가 sh 대신 시작되어야 #!/bin/bash
합니다 #!/bin/sh
.
((…))
Sh에는 산술 표현식에 대한 구문이 없습니다 . 하지만 여기서는 필요하지 않으며 이식 가능한 조건 구문을 사용할 수 있습니다 [ … ]
. [ … ]
조건문 에는 "보다 작음" 연산자를 씁니다 -lt
.
중괄호는 {1..2}
sh에 존재하지 않는 또 다른 bash 기능입니다. 스크립트의 또 다른 실수는 if is 값 과 마찬가지로 문자열로 X=$A+1
설정된다는 것입니다 . 산술 계산을 수행하려면 산술 표현식 구문을 사용해야 합니다 .X
42+1
A
42
$((…))
또한 일반적인 의견으로는,변수 대체에는 항상 큰따옴표를 사용하십시오..
코드의 또 다른 문제는 A
십진수처럼 보인다는 것입니다. 쉘 연산은 정수에서만 작동합니다. 알고리즘을 조정했지만 작동 방식을 확인하면 원하는 방식으로 반올림되지 않을 수 있습니다. awk를 사용하여 줄 수를 계산하는 것은 약간 과잉입니다. wc -l
이것이 더 깨끗하고 빠른 방법입니다. 마찬가지로, 파일의 처음 N 줄을 인쇄하려면 head
.
$i_chunk
또 다른 실수는 변수의 값 입니다 i_chunk
. i
값을 가져와 추가하려면 _chunk
변수 이름을 중괄호( )로 구분해야 합니다 ${i}_chunk
.
j
나는 루프가 무엇을 해야 할지 전혀 몰랐고 그냥 내버려두었습니다.
#!/bin/sh
for i in 1 2
do
input="../ExpressionSet_${i}_chunk.txt"
for j in 1 2
do
A=$(wc -l <"$input")
Y=100
X=0
if [ "$A" -lt "$Y" ]; then
X=$((A+100))
else
X=$A
fi
head -n "$((X/100))" "$input" > "$i"_top1pc.txt
head -n "$((X/20))" "$input" > "$i"_top5pc.txt
done
done
Bash 스크립트 작성을 선택하면 다음과 같은 여러 Bash 기능을 활용할 수 있습니다.
((…))
산술 평가용(그러나 여전히 정수만 가능)typeset -i
산술 표현식을 할당하여 평가할 수 있도록 정수 변수를 선언합니다.
#!/bin/bash
for i in 1 2
do
input="../ExpressionSet_${i}_chunk.txt"
for j in 1 2
do
A=$(wc -l <"$input")
Y=100
typeset -i X
if ((A < Y)); then
X=A+100
else
X=$A
fi
head -n "$((X/100))" "$input" > "$i"_top1pc.txt
head -n "$((X/20))" "$input" > "$i"_top5pc.txt
done
done