我有对话转录的文本文件,例如:
Speaker1: Hello.
Speaker2: Hi.
Speaker2: How are you?
Speaker1: Well thanks.
我想数一下说话者有多少次变化从一行到另一行。因此,对于本示例,它将是 2(第 1 行到第 2 行,第 3 行到第 4 行,但不是第 2 行到第 3 行)。
答案1
$ awk -F':' '(NR>1) && ($1!=prev){c++} {prev=$1} END{print c+0}' file
2
答案2
Python 模块itertools
有一个方法groupby
,只要键值发生变化,就会对键上的数据进行分组。我们将冒号分隔的第一个字段作为我们的键并围绕它进行分组。
python3 -c 'import sys, itertools as it
k,g = -1,lambda x: x.split(":")[0]
with open(sys.argv[1]) as f:
for t in it.groupby(f,g): k += 1
print(k)
' file
2
GNU sed
可以通过一次查看两行来完成。当冒号分隔的第一个字段不同时,我们会在保留处附加换行符。在 eof 处,在删除一个换行符后打印保留,以说明打印时 sed 隐式添加的换行符。
sed -En '
$!N
/^([^:]+:).*\n\1/!{x;s/$/\n/;x;}
$!D
g;s/.//p
' file|wc -l
Perl 在 slurp 模式 (0777) 下,使用正则表达式的功能,删除在冒号上分隔的相同第一个字段的连续重复行。然后计算换行符的数量。
perl -pl -0777 -e '
s/^(([^:]+:).*\n)(?:\2.*\n)+/$1/mg;
$_ = tr/\n// -1;
' file
答案3
累积的“管道”方法如下所示:
- 剪切说话者后面的所有内容(第一个冒号):
cut -f1 -d:
- 消除重复:
uniq
- 计数行:
wc -l
因此,cut -f1 -d: < yourfile | uniq | wc -l
应该会产生期望的结果。
更新
正如 @EdMorton 观察到的,结果相差一(变化行数减一,上面算的是行数)。如果您可以管理它,请考虑到这一点。否则,您可以添加一个阶段来跳过uniq
:之后的第一行uniq | tail -n +2
。
答案4
使用 Raku(以前称为 Perl_6)
raku -e '(-1 + slurp.split(/<[:\v]>/)[0,2,4...*]>>.match(/\d+$/).[0..(*-2)]>>.Int.squish.elems).say;'
或者
raku -e '(-1 + slurp.comb(/ ^^ \w+ <(\d+)> \: \s /).squish.elems).say;'
简而言之(上面的第二个解决方案),slurp
文件comb
选择(按顺序)匹配^^
行首、\w+
alnum(s)、\:
冒号和\s
空格的元素,使用<(…)>
运算符删除除数字之外的所有内容,squish
相邻的相同数字只留下一个,获取元素数量elems
,然后-1
(减一)得出say
答案。
示例输入(OP,重复 2X):
Speaker1: Hello.
Speaker2: Hi.
Speaker2: How are you?
Speaker1: Well thanks..
Speaker1: Hello.
Speaker2: Hi.
Speaker2: How are you?
Speaker1: Well thanks..
Speaker1: Hello.
Speaker2: Hi.
Speaker2: How are you?
Speaker1: Well thanks..
示例输出 ( perl6 -e 'slurp.comb(/ ^^ \w+ <(\d+)> \: \s /).say;'
)
(1 2 2 1 1 2 2 1 1 2 2 1)
示例输出 ( perl6 -e 'slurp.comb(/ ^^ \w+ <(\d+)> \: \s /).squish.say;'
)
(1 2 1 2 1 2 1)
示例输出(最后,从顶部开始的第二行代码):
6