将句子拆分成单独的行

Split sentences into separate lines

我正在尝试使用 shell 脚本将文件中的句子拆分成单独的行。

现在我想用 !, ? 分割字符串要么 。 .输出应该是这样的:

我想从 my_text.txt 中读取并包含

的文件

you want to learn shell script? First, you want to learn Linux command! then. you can learn shell script.

现在我想用“!”或“?”或“.”拆分字符串。输出应该是这样的:

you want to learn shell script                 
First, you want to learn Linux command             
then           
you can learn shell script

我用过这个脚本:

while read p
do
   echo $p | tr "? ! ." "\n " 
done < my_text.txt

但输出是:

you want to learn shell script

First, you want to learn Linux command then you can learn shell script

有人可以帮忙吗?

Awk 非常适合这个:

awk -F '[?.!]' '{ for (i=1;i<=NF;i++) { print $i } }' file

将字段分隔符设置为?要么 。要么 !然后遍历每个字段并打印条目。

您可以调用 3 个 tr 命令拆分 ? !和.

cat test_string.txt | tr "!" "\n" | tr "?" "\n" | tr "." "\n"

这可以在单个 awk 中使用其全局替换选项完成,如下所示,仅在 GNU awk 中使用所示示例编写和测试。只需全局替换 ?!. 为新行(默认情况下 ORS(输出记录分隔符)值作为新行)。

awk '{gsub(/\?|!|\./,ORS)} 1' Input_file

那不是您使用 tr 的方式。它的两个参数的长度应该相同,否则第二个参数将通过重复其最后一个字符 * 扩展到第一个的长度——也就是说,在这种情况下,一个 space—使逐一音译成为可能。换句话说,给定 ? ! .\n 作为参数,tr 将用换行符替换 ?,而 ! . 与 space。我猜你要找的是:

$ tr '?!.' '\n' <file
you want to learn shell script
 First, you want to learn Linux command
 then
 you can learn shell script

或者,更方便地说:

tr '?!.' '[\n*]' <file

*这就是 GNU tr 所做的,POSIX 在参数长度不同时未指定行为。

gnu-awk中我们可以用gensub()函数得到:

awk '{print gensub(/([.?!]\s*)/, "\n", "g", [=10=])}' file
you want to learn shell script
First, you want to learn Linux command
then
you can learn shell script

$ sed 's/[!?.]/\n/g' file
you want to learn shell script
 First, you want to learn Linux command
 then
 you can learn shell script

为什么要将自己限制在新行\n 作为 RS?也许是这样的:

  • \056 是句点。 \040 是 space。如果有,我会添加 + 是在每个句子和 u 之后键入 2 spaces 的传统做法 想要标准化它。
  • 我假设问号 \044 更频繁 而不是感叹\041。我使用全八进制的唯一原因是 所有这些都是可以在终端上破坏 havor 的东西 没有正确引用和转义的可能性很小。
  • 与 FS 或 RS 不同,OFS/ORS 是常量字符串(是吗?),因此输入字符是安全的。
  • 经期由 RS 负责。无需特殊处理。那么,如果该行两者都不包含?也不! ,按原样打印,然后继续(它将处理 ".\n" )

.

mawk 'BEGIN { RS = "[6][0]+" ; ORS = ". \n"; 
              FS = "[4][0]+";  OFS = "? \n"; }
      ([=10=] !~ /[14]/) { 
                              print; next; } 
             /[1]/      { 
                              gsub("[1][0]+", "1 \n"); }  
      ( NF==1 ) || ( = )'

和 mawk 一样快,gsub ( ) 或 $1=$1 仍然要花钱,所以跳过昂贵的部分,除非它实际上有一个 ?要么 !马克.

最后一行是有趣的技巧,*在大括号之外完成。你已经完成了!之前的那一行,所以如果没有?找到(又名 NF 为 1),然后那个评估为真,awk 将短路并且不执行第 2 部分,只需打印。

但是如果你找到了?标记, $1=$1 的赋值将以新的顺序重新排列它们,并且因为它是一个赋值操作而不是相等比较,如果赋值本身没有失败,它总是返回成功,这也将作为它自己的始终-true 标志打印到最后。

Awk 的记录分隔符变量 RS 应该可以解决问题。

echo 'you want to learn shell script? First, you want to learn Linux command! then. you can learn shell script.' |
awk 'BEGIN{RS="[?.!] "}1'