如何在 bash 中在每个段落的开头插入文本

如何在 bash 中在每个段落的开头插入文本

我有一个文件,其中有多个段落,每个段落之间用空行分隔。从技术上讲,它们不是段落,只是用空行分隔的文本部分。

我想通过在每行的第一行空白行后插入一个数字来对段落进行编号。因此,如果我的文件显示:

这是文本。
这是更多文本。
更多文字!

这是第二部分的文字。
更多文字。
你明白了...

我想让它说:

1这是文本
这是更多文本
更多文字!

2这是第二部分的文字。
更多文字。
你明白了...

答案1

使用 bash 内置命令尝试一下:

#!/bin/bash

l=1                          # paragraph counter
echo -n $l                   # print paragraph counter without new line
while read x; do             # read current line from file, see last line
  if [[ $x == "" ]]; then    # empty line?
    echo                     # print empty line
    read x                   # read next line from file, see last line
    ((l++))                  # increment paragraph counter
    echo -n $l               # print paragraph counter without new line
  fi
  echo "$x"                  # print current line
done < file

答案2

通常,使用 shell 进行文本解析非常缓慢且繁琐。以下是其他一些选项:

  1. Perl 的“段落模式”

    perl -00pe 's/^/$./' file 
    

    解释

    打开-00段落模式,其中“行”由连续的 定义\n\n,换句话说就是段落。将用当前“行”(段落)号s/^/$./替换行的开头( ) 。告诉 perl 在运行给定的脚本后打印输入文件的每一行。^$.-p-e

  2. awk 的

    awk -vRS='\n\n' -vORS='\n\n' '{print NR$0}' file
    

    解释

    -vRS='\n\n'将 awk 的记录分隔符设置为连续的换行符。与 perl 的段落模式一样,这使它将段落视为“行”。然后我们告诉它打印当前行号 ( NR) 和当前“行” $0-vORS=将输出记录分隔符设置为连续的换行符,以便段落在输出中也由空行分隔。请注意,这将在输出末尾添加 2 个空行。为了避免这种情况,您可以使用head

    awk -v RS='\n\n' -vORS='\n\n' '{print NR$0}' file | head -n -2
    

作为比较,以下是在我的系统上运行 10M 测试文件时各种解决方案所花费的时间:

$ time a.sh > /dev/null ## a.sh is Cyrus's solution

real    0m1.419s
user    0m1.308s
sys     0m0.104s

$ time perl -00pe 's/^/$./' file  > /dev/null 

real    0m0.087s
user    0m0.084s
sys     0m0.000s

$ time awk -v RS='\n\n' -vORS='\n\n' '{print NR$0}' file | head -n -2 >/dev/null

real    0m0.074s
user    0m0.056s
sys     0m0.020s

正如您上面所看到的,perl 和 awk 解决方案都比 shell 方法快一个数量级。

相关内容