Captura Variável e Aritmética For-Loop

0

Meus arquivos de entrada são uma única coluna com comprimento variável de linhas. Meu código deve contar essas linhas e imprimir um número especificado. O problema que estou tendo, é se o número de linhas capturadas na variável "A" é menor que 1, eu quero imprimir pelo menos 1 linha para que o arquivo de saída não esteja vazio. Se "A" (1% do número total de linhas) for maior que 1, quero imprimir esse número de linhas. Meu código awk-bash híbrido é assim:

#!/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

Confusamente, continuo recebendo mensagens de erro como

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")

A propósito, inputFile1 possui 24 linhas e inputFile2 possui 4724 linhas. Obrigado pela ajuda!

    
por Greyson B 14.07.2016 / 17:44

1 resposta

2

Eu acho que seu problema raiz é que você tentou usar a sintaxe bash em um script sh. Bash define extensões para o denominador comum sh; Se você quiser usar recursos específicos do bash, seu script deve começar com #!/bin/bash , não #!/bin/sh .

Sh não possui a sintaxe ((…)) para expressões aritméticas. Mas você não precisa dele aqui, você pode usar a sintaxe condicional [ … ] . No [ … ] condicional, o operador “menor que” é escrito -lt .

Chaves {1..2} são outro recurso bash que não existe no sh. Outro erro no seu script é X=$A+1 , que define X como uma string como 42+1 se o valor de A for 42 ; Para realizar um cálculo aritmético, você precisa usar a sintaxe de expressão aritmética $((…)) .

Além disso, como observação geral, sempre use aspas duplas em volta das substituições de variáveis .

Outro problema com seu código é que parece que A é um número decimal. A aritmética da shell só funciona com números inteiros. Eu adaptei o algoritmo, mas verifique o que ele faz, eu poderia não ter arredondado a maneira que você pretendia. Usar o awk só para contar o número de linhas é um exagero, wc -l é uma maneira mais clara e rápida de fazer isso. Da mesma forma, para imprimir as primeiras N linhas de um arquivo, basta chamar head .

Ainda outro erro é que $i_chunk é o valor da variável i_chunk . Para obter o valor de i e acrescentar _chunk , você precisa delimitar o nome da variável com chaves: ${i}_chunk .

Eu não tenho ideia do que o loop em j deveria estar fazendo, deixei isso em paz.

#!/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

Se você optar por escrever um script bash, poderá usar vários recursos do bash:

  • ((…)) para avaliações aritméticas (mas ainda apenas inteiras)
  • typeset -i para declarar uma variável inteira, de forma que atribuir uma expressão aritmética a avalia
#!/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
    
por 15.07.2016 / 03:39

Tags