向 Grep 添加制表符分隔符

Posted

技术标签:

【中文标题】向 Grep 添加制表符分隔符【英文标题】:Add Tab Separator to Grep 【发布时间】:2011-02-01 00:06:37 【问题描述】:

我是 grep 和 awk 的新手,我想在“frequency.txt”文件输出中创建制表符分隔值(此脚本查看一个大型语料库,然后输出每个单词及其使用次数在语料库中-我将其修改为高棉语)。我环顾四周(grep a tab in UNIX),但似乎找不到对我来说对这个 bash 脚本有意义的示例(我太新手了)。

我在 cygwin 中使用这个 bash 脚本:

#!/bin/bash
# Create a tally of all the words in the corpus.
#
echo Creating tally of word frequencies...
#
sed -e 's/[a-zA-Z]//g' -e 's/​/ /g' -e 's/\t/ /g' \
    -e 's/[«|»|:|;|.|,|(|)|-|?|។|”|“]//g' -e 's/[0-9]//g' \
    -e 's/ /\n/g' -e 's/០//g' -e 's/១//g' -e 's/២//g' \
    -e 's/៣//g' -e 's/៤//g' -e 's/៥//g' -e 's/៦//g' \
    -e 's/៧//g' -e 's/៨//g' -e 's/៩//g' dictionary.txt | \
  tr [:upper:] [:lower:] | \
  sort | \
  uniq -c | \
  sort -rn > frequency.txt
grep -Fwf dictionary.txt frequency.txt | awk 'print $2 "," $1'

Awk 使用逗号打印,但这只是在屏幕上。如何在频率和术语之间放置一个制表符(逗号也可以)?

这是 dictionary.txt 文件的一小部分(高棉语不使用空格,但在这个语料库中,每个单词之间有一个不间断的空格,使用 sed 和正则表达式转换为空格):

ព្រះ​វិញ្ញាណ​នឹង​ប្រពន្ធ​ថ្មោង​ថ្មី​ពោល​ថា អញ្ជើញ​មក ហើយ​អ្នក​ណា​ដែល​ឮ​ក៏​ថា អញ្ជើញ​មក​ដែរ អ្នក​ណា​ដែល​ស្រេក នោះ​មាន​តែ​មក ហើយ​អ្នក​ណា​ដែល​ចង់​បាន មាន​តែ​យក​ទឹក​ជីវិត​នោះ​ចុះ ឥត​ចេញ​ថ្លៃ​ទេ។

这是频率.txt 现在的示例输出(频率和术语):

25605 នឹង 25043 ជា 22004 បាន 20515 នោះ

我希望输出频率.txt 看起来像这样(其中 TAB 是实际的制表符):

25605TABនឹង 25043TABជា 22004TABបាន 20515TABនោះ

感谢您的帮助!

【问题讨论】:

如果您提供一个样本来说明语料库文件dictionary.txt 的样子会更好,因为我几乎可以肯定您可以通过对awk 的一次调用来替换整个脚本。即不会使用tr, sort, uniq, sed, or grep 我在原始问题中添加了字典文本文件的示例 - 谢谢! @Nathan 该字典文件使用什么编码?它在我的屏幕上看起来像垃圾:见i.imgur.com/Ao82s.png @SiegeX 它是 UTF-8 - 大量的东西还不支持高棉 Unicode。 @Nathan 是 dictionary.txt 只是一堆单词,可能不止一个,一行由空格分隔?还是一个单词列表,每行一个单词? 【参考方案1】:

你应该可以用这个替换整个冗长的sed 命令:

tr -d '[a-zA-Z][0-9]«»:;.,()-?។”“|០១២៣៤៥៦៧៨៩'
tr '\t' ' '

评论:

's/​/ /g' - 前两个斜杠表示重新使用之前的匹配项 [a-z][A-Z] 并用空格替换它们,但它们已被删除,所以这是一个无操作 's/[«|»|:|;|.|,|(|)|-|?|។|”|“]//g' - 竖线字符不分隔方括号内的替代项,它们是字面意思(不止一个是多余的),等价的将是 's/[«»:;.,()-?។”“|]//g' (留下一个竖线以防你真的想删除它们)李> 's/ /\n/g' - 之前,您将制表符替换为空格,现在您将空格替换为换行符

您应该能够通过在uniq 之后将其插入管道中来获得所需的选项卡:

sed 's/^ *\([0-9]\+\) /\1\t/'

如果您希望 AWK 命令输出选项卡:

awk 'BEGINOFS='\t' print $2, $1'

【讨论】:

谢谢丹尼斯。正如你所说,我在添加标签时遇到问题,当我在 uniq 之后添加 sed 's/^ *([0-9]\+) /\1\t/' 脚本在最后停止并且永远不会填充我的频率。文本文件。我是否正确理解您,我只是在 uniq 下方添加 sed 's/^ *([0-9]\+) /\1\t/' 一行? @Nathan:是的,您需要添加必要的管道字符。就像你有uniq -c | \` now, you would need sed ... | \` (实际上不需要续行反斜杠,因为管道会为您续行)。 谢谢丹尼斯,我从来没有使用过 bash 脚本,所以我不熟悉语法。感谢您花时间帮助我!【参考方案2】:

用“

【讨论】:

是的,这确实有效,但它并不理想,因为现在屏幕上没有任何正在发生的状态(除了我的 cpu 显示器,我不知道它正在工作)。还有其他方法吗?谢谢你 - 至少这是可能的。【参考方案3】:

下面的脚本应该可以带你去你需要去的地方。到tee 的管道将让您在屏幕上看到输出,同时将输出写入./outfile

#!/bin/sh  

sed ':a;N;s/[a-zA-Z0-9។០១២៣៤៥៦៧៨៩\n«»:;.,()?”“-]//g;ta' < dictionary.txt | \
gawk '$0=toupper($0);for(i=1;i<=NF;i++)a[$i]++
   ENDfor(item in a)printf "%s\t%d ", item, a[item]' | \
tee ./outfile

【讨论】:

以上是关于向 Grep 添加制表符分隔符的主要内容,如果未能解决你的问题,请参考以下文章

制表符分隔文件中的引号

cut命令

grep 单词并检索匹配项和以下以制表符开头的行

linux 中 grep命令匹配空格和制表符

Linux篇--awk的使用

第10章 Shell编程_字符截取命令