获取零的长度(被一个打断)
Get lengths of zeroes (interrupted by ones)
我有一长列 1 和 0:
0
0
0
1
0
0
0
0
0
1
0
0
0
0
0
1
0
0
1
....
我可以很容易地得到 1 之间的平均零数(只是 total/ones):
ones=$(grep -c 1 file.txt)
lines=$(wc -l < file.txt)
echo "$lines / $ones" | bc -l
但是我怎样才能得到一个之间的零字符串的长度呢?在上面的简短示例中,它将是:
3
5
5
2
编辑:修复了最后一行是 0
的情况
awk 简单:
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
您可以使用 awk
:
awk '=="0"{s++} =="1"{if(s)print s;s=0} END{if(s)print(s)}'
解释:
特殊变量</code>包含一行文本的第一个<em>字段</em>(<em>列</em>)的值。除非您使用 <code>-F
命令行选项指定字段分隔符,否则它默认为宽空格 - 这意味着 </code> 将在您的示例中包含 <code>0
或 1
。
如果 </code> 的值等于 <code>0
,则名为 s
的变量将递增,但如果 </code> 等于 <code>1
的当前值s
被打印(如果大于零)并重新初始化为 0
。 (注意 awk 在第一次增量操作之前用 0
初始化 s
)
END
块在处理完最后一行输入后执行。如果文件以 0
(s) 结尾,将打印文件末尾和最后一个 1
之间的 0
秒数。 (如果没有 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 '{print c; c=0} !{c++}' file
3
5
5
2
如果您的 file.txt 只是 一列 1 和 0,您可以使用 awk
并将记录分隔符更改为“1\n”。这使得每个 "record" 都是“0\n”的序列,并且记录中 0 的计数是记录的长度除以 2。前导和尾随 1 和 0 的计数将是正确的。
awk 'BEGIN {RS="1\n"} { print length/2 }' file.txt
使用 awk
,我会使用值为 0
的字段计算为 False 的事实:
awk '!{s++; next} {if (s) print s; s=0} END {if (s) print s}' file
这个returns:
3
5
5
2
另外,请注意 END
块打印出现在最后一个 1
.
之后的任何 "remaining" 零
说明
!{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.
我的尝试。不是很漂亮但是.. :3
grep -n 1 test.txt | gawk '{y=-x; print y-1; x=}' FS=":"
输出:
3
5
5
2
另一种方式:
perl -lnE 'if(m/1/){say $.-1;$.=0}' < file
"reset" 1
.
时的行计数器
打印
3
5
5
2
今天这个问题似乎很受欢迎。加入晚会,这是另一个简短的 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 }'
最简单的解决方案是将 sed
与 awk
一起使用,如下所示:
sed -n '$bp;/0/{:r;N;/0$/{h;br}};/1/{x;bp};:p;/.\+/{s/\n//g;p}' input.txt \
| awk '{print length}'
解释:
sed
命令分隔 0
并创建如下输出:
000
00000
00000
00
通过管道传输到 awk '{print length}'
您可以获得每个间隔的 0
计数:
输出:
3
5
5
2
一个有趣的,纯粹的 Bash:
while read -d 1 -a u || ((${#u[@]})); do
echo "${#u[@]}"
done < file
这告诉 read
使用 1
作为分隔符,即,一旦遇到 1
就停止阅读; read 将 0
存储在数组 u
的字段中。那么我们只需要用${#u[@]}
统计u
中的字段个数。 || ((${#u[@]}))
在这里是为了防止您的文件不以 1
.
结尾
更奇怪(且不完全正确)的方式:
perl -0x31 -laE 'say @F+0' <file
打印
3
5
5
2
0
它
- 读取记录分隔符设置为字符
1
的文件-0x31
- 自动拆分
-a
(将记录拆分到数组 @F
)
- 并打印
@F
中的元素数量,例如say @F+0
或者可以使用 say scalar @F
不幸的是,在最后的 1
(作为记录分隔符)之后,它打印了一个空记录 - 因此打印了最后一个 0
.
这是不正确的解决方案,仅作为替代好奇心显示。
扩展,你可以说:
$ uniq -c file | awk '! {print }'
3
5
5
2
从man uniq
我们看到uniq
的目的是:
Filter adjacent matching lines from INPUT (or standard input), writing
to OUTPUT (or standard output).
因此 uniq
将数字分组。使用 -c
选项,我们得到一个带有出现次数的前缀:
$ uniq -c file
3 0
1 1
5 0
1 1
5 0
1 1
2 0
1 1
然后是打印 0
之前的那些计数器的问题。为此,我们可以使用 awk
,例如:awk '! {print }'
。即:如果字段是0
.
则打印第二个字段
我有一长列 1 和 0:
0
0
0
1
0
0
0
0
0
1
0
0
0
0
0
1
0
0
1
....
我可以很容易地得到 1 之间的平均零数(只是 total/ones):
ones=$(grep -c 1 file.txt)
lines=$(wc -l < file.txt)
echo "$lines / $ones" | bc -l
但是我怎样才能得到一个之间的零字符串的长度呢?在上面的简短示例中,它将是:
3
5
5
2
编辑:修复了最后一行是 0
的情况awk 简单:
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
您可以使用 awk
:
awk '=="0"{s++} =="1"{if(s)print s;s=0} END{if(s)print(s)}'
解释:
特殊变量</code>包含一行文本的第一个<em>字段</em>(<em>列</em>)的值。除非您使用 <code>-F
命令行选项指定字段分隔符,否则它默认为宽空格 - 这意味着 </code> 将在您的示例中包含 <code>0
或 1
。
如果 </code> 的值等于 <code>0
,则名为 s
的变量将递增,但如果 </code> 等于 <code>1
的当前值s
被打印(如果大于零)并重新初始化为 0
。 (注意 awk 在第一次增量操作之前用 0
初始化 s
)
END
块在处理完最后一行输入后执行。如果文件以 0
(s) 结尾,将打印文件末尾和最后一个 1
之间的 0
秒数。 (如果没有 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 '{print c; c=0} !{c++}' file
3
5
5
2
如果您的 file.txt 只是 一列 1 和 0,您可以使用 awk
并将记录分隔符更改为“1\n”。这使得每个 "record" 都是“0\n”的序列,并且记录中 0 的计数是记录的长度除以 2。前导和尾随 1 和 0 的计数将是正确的。
awk 'BEGIN {RS="1\n"} { print length/2 }' file.txt
使用 awk
,我会使用值为 0
的字段计算为 False 的事实:
awk '!{s++; next} {if (s) print s; s=0} END {if (s) print s}' file
这个returns:
3
5
5
2
另外,请注意 END
块打印出现在最后一个 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.
我的尝试。不是很漂亮但是.. :3
grep -n 1 test.txt | gawk '{y=-x; print y-1; x=}' FS=":"
输出:
3
5
5
2
另一种方式:
perl -lnE 'if(m/1/){say $.-1;$.=0}' < file
"reset" 1
.
打印
3
5
5
2
今天这个问题似乎很受欢迎。加入晚会,这是另一个简短的 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 }'
最简单的解决方案是将 sed
与 awk
一起使用,如下所示:
sed -n '$bp;/0/{:r;N;/0$/{h;br}};/1/{x;bp};:p;/.\+/{s/\n//g;p}' input.txt \
| awk '{print length}'
解释:
sed
命令分隔 0
并创建如下输出:
000
00000
00000
00
通过管道传输到 awk '{print length}'
您可以获得每个间隔的 0
计数:
输出:
3
5
5
2
一个有趣的,纯粹的 Bash:
while read -d 1 -a u || ((${#u[@]})); do
echo "${#u[@]}"
done < file
这告诉 read
使用 1
作为分隔符,即,一旦遇到 1
就停止阅读; read 将 0
存储在数组 u
的字段中。那么我们只需要用${#u[@]}
统计u
中的字段个数。 || ((${#u[@]}))
在这里是为了防止您的文件不以 1
.
更奇怪(且不完全正确)的方式:
perl -0x31 -laE 'say @F+0' <file
打印
3
5
5
2
0
它
- 读取记录分隔符设置为字符
1
的文件-0x31
- 自动拆分
-a
(将记录拆分到数组@F
) - 并打印
@F
中的元素数量,例如say @F+0
或者可以使用say scalar @F
不幸的是,在最后的 1
(作为记录分隔符)之后,它打印了一个空记录 - 因此打印了最后一个 0
.
这是不正确的解决方案,仅作为替代好奇心显示。
扩展
$ uniq -c file | awk '! {print }'
3
5
5
2
从man uniq
我们看到uniq
的目的是:
Filter adjacent matching lines from INPUT (or standard input), writing to OUTPUT (or standard output).
因此 uniq
将数字分组。使用 -c
选项,我们得到一个带有出现次数的前缀:
$ uniq -c file
3 0
1 1
5 0
1 1
5 0
1 1
2 0
1 1
然后是打印 0
之前的那些计数器的问题。为此,我们可以使用 awk
,例如:awk '! {print }'
。即:如果字段是0
.