ファイル内の1行あたりのタブ数を計算し、条件が一致した場合は、その行を別のファイルに印刷しようとします。ただし、スクリプトは最初の行のみを読み取って終了します。
以下で何が問題なのか教えてください。
#!/bin/bash
set -e
set -o pipefail
filename="0101.tsv"
while IFS= read -r line;do
s=$(awk '{print gsub(/\t/,"")}')
echo $s
if [[ $s -eq 995 ]]; then
printf "%s\n" "$line"
continue
fi
done < $filename > abc.tsv
ありがとうございます! 。
答え1
ファイル内のタブで区切られたフィールドの数を計算したいようです。これを行うには、タブで入力行を分割して数を数える必要があります。 awk
これは自動的に行うことができ、結果フィールド数の特殊変数もありますNF
。
996フィールド(995ラベル)を含むすべての行を印刷したい場合:
awk -F '\t' 'NF == 996' <file
これは短縮された方法です。
awk 'BEGIN { FS = "\t" } NF == 996 { print }' <file
つまり、入力レコード(行)の印刷print
を意味するのは、入力フィールド区切り記号です。print $0
FS
ファイルからテキスト行を抽出し、それらをループ内の同様のツールに渡すか、それを通過するawk
たびsed
に常に同じ操作を実行するより効率的な方法があります。上記のコマンドはawk
一度だけ呼び出されますが、ソリューション(データが正しく渡された場合)はファイル内のすべての行awk
に対して呼び出されます。awk
答え2
@steeldriverのonelinerはこれをawk
行うことができますが、bashシェルスクリプトで行を読むには、次のようにします。
#!/bin/bash
set -e
set -o pipefail
filename="0101.tsv"
while IFS= read -r line
do
s=0
len=${#line}
# echo "line=$line"
# echo "len=$len"
for (( i=0; i<$len; i++ ))
do
if [ "${line:i:1}" == $'\t' ]
then
s=$((s +1))
fi
done
echo $s
if [[ "$s" == "995" ]]; then
printf "%s\n" "$line"
continue
fi
done < "$filename" > abc.tsv