hig*_*guy 7 command-line text-processing
我有一个长文本文件(stardict-editor 的标签文件),它由以下格式的行组成:
word1 some text
word1 some other text
word2 more text
word3 even more
Run Code Online (Sandbox Code Playgroud)
并想将其转换为
word1 some text<br>some other text
word2 more text
word3 even more
Run Code Online (Sandbox Code Playgroud)
这意味着以相同单词开头的后续行(文件已排序)应合并为一个(此处定义用 分隔<br>)。具有相同开头的行也可以出现不止两次。分隔单词和定义的字符是制表符,每行都是唯一的。word1, word2,word3当然是我事先不知道的任意内容(制表符和换行符除外)的占位符。
我可以想到一段较长的 Perl 代码来执行此操作,但想知道 Perl 中是否有简短的解决方案或命令行的某些内容。有任何想法吗?
perl -p0E 'while(s/^((.+?)\t.*)\n\2\t/$1<br>/gm){}'
Run Code Online (Sandbox Code Playgroud)
(在我用了 6 年的笔记本电脑上,处理一个 23MB、1.5M 行的字典需要 2 秒)
这是标准程序awk
awk '
{
k=$2
for (i=3;i<=NF;i++)
k=k " " $i
if (! a[$1])
a[$1]=k
else
a[$1]=a[$1] "<br>" k
}
END{
for (i in a)
print i "\t" a[i]
}' long.text.file
Run Code Online (Sandbox Code Playgroud)
如果文件按行中的第一个单词排序,则脚本可以更简单
awk '
{
if($1==k)
printf("%s","<br>")
else {
if(NR!=1)
print ""
printf("%s\t",$1)
}
for(i=2;i<NF;i++)
printf("%s ",$i)
printf("%s",$NF)
k=$1
}
END{
print ""
}' long.text.file
Run Code Online (Sandbox Code Playgroud)
要不就bash
unset n
while read -r word definition
do
if [ "$last" = "$word" ]
then
printf "<br>%s" "$definition"
else
if [ "$n" ]
then
echo
else
n=1
fi
printf "%s\t%s" "$word" "$definition"
last="$word"
fi
done < long.text.file
echo
Run Code Online (Sandbox Code Playgroud)