我正在尝试计算文件中每行的选项卡数量,并在条件匹配时将该行打印到另一个文件。但脚本只读取第一行并终止。
请让我知道下面有什么问题,
#!/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 的onelinersawk
可以完成这项工作,但是如果你想要一个 bash shellscript 读取行,你可以这样做,
#!/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