Bash 获取零的长度(被1打断)
我有一长列1和0:Bash 获取零的长度(被1打断),bash,awk,Bash,Awk,我有一长列1和0: 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 .... 我可以很容易地得到1之间0的平均数(仅为总数/1): 编辑:修复了最后一行为0的情况 awk中的Easy: awk '/1/{print NR-prev-1; prev=NR;}END{if (NR>prev)print NR-prev;}' 在bash中也不难: i=0 for x in $(<file.txt); do if ((x)); then echo $i;
0
0
0
1
0
0
0
0
0
1
0
0
0
0
0
1
0
0
1
....
我可以很容易地得到1之间0的平均数(仅为总数/1):
编辑:修复了最后一行为0的情况 awk中的Easy:
awk '/1/{print NR-prev-1; prev=NR;}END{if (NR>prev)print NR-prev;}'
在bash中也不难:
i=0
for x in $(<file.txt); do
if ((x)); then echo $i; i=0; else ((++i)); fi
done
((i)) && echo $i
i=0
对于美元形式的x(您可以使用awk
:
awk '$1=="0"{s++} $1=="1"{if(s)print s;s=0} END{if(s)print(s)}'
说明:
-F '\n' # set input field separator as \n (newline)
-v RS='(1\n)+' # set input record separator as multipled of 1 followed by newline
NF # execute the block if minimum one field is found
print NF-1 # print num of field -1 to get count of 0
特殊变量$1
包含一行文本的第一个字段(列)的值。除非您使用-F
命令行选项指定字段分隔符,否则它默认为宽空间,这意味着$1
在您的示例中将包含0
或1
如果$1
的值等于0
,则称为s
的变量将递增,但如果$1
等于1
,则打印s
的当前值(如果大于零)并重新初始化为0
。(请注意,在第一次增量操作之前,awk使用0
初始化s
)
END
块在处理完最后一行输入后执行。如果文件以0
(s)结尾,则将打印文件结尾和最后一行1
之间的0
s个数。(如果没有END
块,则不会打印)
输出:
3
5.
5.
2.
如果可以使用perl
:
perl -lne 'BEGIN{$counter=0;} if ($_ == 1){ print $counter; $counter=0; next} $counter++' file
3
5
5
2
使用awk
相同的逻辑,它实际上看起来更好:
awk '$1{print c; c=0} !$1{c++}' file
3
5
5
2
如果file.txt只是一列1和0,则可以使用awk
并将记录分隔符更改为“1\n”。这使每个“记录”都是一个“0\n”序列,记录中的0的计数是记录长度除以2。前导和尾随的1和0的计数是正确的
awk 'BEGIN {RS="1\n"} { print length/2 }' file.txt
使用awk
,我将使用值为0
的字段计算为False的事实:
awk '!$1{s++; next} {if (s) print s; s=0} END {if (s) print s}' file
这将返回:
3
5
5
2
另外,请注意END
块以打印最后一个1
之后出现的任何“剩余”零
解释
!$1{s++;next}
如果字段为非真,即如果字段为0
,则递增计数器。然后跳到下一行
{if(s)print s;s=0}
否则,打印计数器的值并将其重置,但前提是它包含一些值(以避免在文件以1
开头时打印0
)
END{if(s)print s}
在处理文件后打印计数器的剩余值,但前提是之前没有打印
纯bash:
sum=0
while read n ; do
if ((n)) ; then
echo $sum
sum=0
else
((++sum))
fi
done < file.txt
((sum)) && echo $sum # Don't forget to output the last number if the file ended in 0.
sum=0
读;做
如果((n));那么
回音$sum
总和=0
其他的
((++sum))
fi
完成
我的尝试。不太漂亮,但
grep -n 1 test.txt | gawk '{y=$1-x; print y-1; x=$1}' FS=":"
输出:
另一种方式:
perl -lnE 'if(m/1/){say $.-1;$.=0}' < file
这似乎是今天相当流行的问题。加入党晚了,这里有另一个简短的gnu awk命令来完成这项工作:
awk -F '\n' -v RS='(1\n)+' 'NF{print NF-1}' file
3
5
5
2
工作原理:
-F '\n' # set input field separator as \n (newline)
-v RS='(1\n)+' # set input record separator as multipled of 1 followed by newline
NF # execute the block if minimum one field is found
print NF-1 # print num of field -1 to get count of 0
为了更容易阅读,我将包括uniq
:
uniq -c file.txt | awk '/ 0$/ {print $1}'
最简单的解决方案是将sed
与awk
一起使用,如下所示:
sed -n '$bp;/0/{:r;N;/0$/{h;br}};/1/{x;bp};:p;/.\+/{s/\n//g;p}' input.txt \
| awk '{print length}'
说明:
-F '\n' # set input field separator as \n (newline)
-v RS='(1\n)+' # set input record separator as multipled of 1 followed by newline
NF # execute the block if minimum one field is found
print NF-1 # print num of field -1 to get count of 0
sed
命令分离0
s并创建如下输出:
sed -n '$bp;/0/{:r;N;/0$/{h;br}};/1/{x;bp};:p;/.\+/{s/\n//g;p}' input.txt \
| awk '{print length}'
000
00000
00000
00
通过管道输送到awk'{print length}'
可以获得每个间隔的0
计数:
输出:
-F '\n' # set input field separator as \n (newline)
-v RS='(1\n)+' # set input record separator as multipled of 1 followed by newline
NF # execute the block if minimum one field is found
print NF-1 # print num of field -1 to get count of 0
3
5.
5.
2.
一个有趣的例子,在纯Bash中:
while read -d 1 -a u || ((${#u[@]})); do
echo "${#u[@]}"
done < file
read-d1-a u | |(${#u[@]})时做什么
回声“${u[@]}”
完成<文件
这告诉read
使用1
作为分隔符,即在遇到1
时立即停止读取;read将0
存储在数组u
的字段中。然后我们只需要用${u[@]}
计算u
中的字段数。|(${u[})
在这里只是为了防止您的文件不是以一种更奇怪(且不完全正确)的方式结束:
它
- 将记录分隔符设置为character
1
the-0x31
- 使用自动拆分
-a
(将记录拆分为数组@F
)
- 并打印
@F
中的元素数,例如说@F+0
或可以使用说scalar@F
不幸的是,在最后一个1
(作为记录分隔符)之后,它会打印一个空记录,因此会打印最后一个0
这是一个不正确的解决方案,只显示为另一种好奇心。展开,您可以说:
$ uniq -c file | awk '!$2 {print $1}'
3
5
5
2
从man uniq
我们可以看出uniq
的目的是:
从输入(或标准输入)中过滤相邻的匹配行,写入
输出(或标准输出)
因此,uniq
对数字进行分组。使用-c
选项,我们可以得到一个带有出现次数的前缀:
$ uniq -c file
3 0
1 1
5 0
1 1
5 0
1 1
2 0
1 1
然后是打印0
之前的计数器的问题。为此,我们可以使用awk
例如:awk'!$2{print$1}'
。也就是说:如果字段是0
,则打印第二个字段。您熟悉awk
吗?不,我对此非常陌生。但是,根据答案(我目前正在浏览),看起来学习它会非常有帮助。:)谢谢潜伏者和所有人的回答。看起来我应该学习一些awk
:)注意s=0
是默认值,所以没有必要设置它!我以为默认情况下(在awk中)它应该是1
…谢谢!需要一个结束块(如果文件以一些零结尾怎么办?)在两个print
操作中都应该是if(s)print s
。否则将输出一个(s)空行
$ uniq -c file | awk '!$2 {print $1}'
3
5
5
2
$ uniq -c file
3 0
1 1
5 0
1 1
5 0
1 1
2 0
1 1