可変キャプチャとForループ操作

可変キャプチャとForループ操作

私の入力ファイルは、行の長さが可変である単一の列です。私のコードはこの行を計算し、指定された数字を印刷する必要があります。私が持っている問題は、変数「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設定されることです。算術計算を実行するには、算術式構文を使用する必要があります。X42+1A42$((…))

また、一般的な意見では、変数の置換には常に二重引用符を使用してください。

コードの他の問題は、10進数のようAに見えることです。シェル操作は整数でのみ機能します。アルゴリズムを調整しましたが、どのように動作するかを確認すると、目的の方法に丸められない可能性があります。 awkを使用して行数を計算するのは少し過剰です。wc -lこれがよりクリーンで迅速な方法です。同様に、ファイルの最初のN行を印刷するにはhead

$i_chunk別の実数は変数の値ですi_chunki値を取得して追加するには、_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

おすすめ記事