我有一个文件,其中有多个段落,每个段落之间用空行分隔。从技术上讲,它们不是段落,只是用空行分隔的文本部分。
我想通过在每行的第一行空白行后插入一个数字来对段落进行编号。因此,如果我的文件显示:
这是文本。 这是更多文本。 更多文字! 这是第二部分的文字。 更多文字。 你明白了...
我想让它说:
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 进行文本解析非常缓慢且繁琐。以下是其他一些选项:
Perl 的“段落模式”
perl -00pe 's/^/$./' file
解释
打开
-00
段落模式,其中“行”由连续的 定义\n\n
,换句话说就是段落。将用当前“行”(段落)号s/^/$./
替换行的开头( ) 。告诉 perl 在运行给定的脚本后打印输入文件的每一行。^
$.
-p
-e
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 方法快一个数量级。