sed - sed、xargs 和 stdbuf - 如何从文件中仅获取模式的前 n 个匹配项
问题描述
我有一个带有模式的文件(1 行=1 模式),我想在一个大文本文件中查找 - 在 infile 的每一行中只能找到一个(或没有)模式。一旦找到匹配项,我想在匹配项之前立即检索字符。第一部分是获取 sed 的模式
cat patterns.txt | xargs -I '{}' sed -n 's/{}.*$//p' bigtext.txt
这行得通 - 缺点是我可能会有数十万场比赛。我不想要/不需要所有的比赛 - 1K 点击的公平表示就足够了。这就是我挣扎的地方:我已经读过,为了限制 sed 的点击次数,我应该使用stdbuf
(gstdbuf
在我的情况下)并将整个事情通过头部管道。但我不确定在哪里放置stdbuf
命令:
cat patterns.txt | xargs -I '{}' gstdbuf -oL -eL sed -n 's/{}.*$//p' bigtext.txt | head -n100
当我尝试这个时,这个过程需要的时间就像它在整个文件上运行 sed 然后得到head
那个输出一样,而我希望在 100 或 1000 个匹配后停止搜索。关于实现这一目标的最佳方法的任何想法?
解决方案
您可以指定一个具有与 grep 命令匹配的模式的文件-f file
。您还可以指定退出前要查找的匹配项数-m count
因此,此命令将为您提供匹配的前 5 行:
grep -f patterns.txt -m 5 bigtext.txt
现在将匹配修剪到行尾,有点困难。假设您使用 bash,我们可以从文件中构建一个正则表达式,如下所示:
while IFS='' read -r line || [[ -n "$line" ]]; do
subRegex="s/$line.*//;"${subRegex}
done < patterns.txt
然后在 sed 命令中使用它。结果代码变为:
while IFS='' read -r line || [[ -n "$line" ]]; do
subRegex="s/$line.*//;"${subRegex}
done < patterns.txt
grep -f patterns.txt -m 5 bigtext.txt | sed "$subRegex"
sed 命令仅在已经从 grep 匹配的行上运行,因此它应该是相当高效的。
现在,如果你经常调用它,你可以把它放在一个函数中
function findMatches() {
local matchCount=${1:-5} # default to 5 matches
local subRegex
while IFS='' read -r line || [[ -n "$line" ]]; do
subRegex="s/$line.*//;"${subRegex}
done < patterns.txt
grep -f patterns.txt -m ${matchCount} bigtext.txt | sed "${subRegex}"
}
然后你可以这样称呼它
findMatches 5
findMatches 100
更新
根据您提供的示例文件,此解决方案确实产生了预期的结果1aaa 2aaabbb 3aaaccc 4aaa 5aaa
但是,鉴于您对每个模式的长度为 120 个字符的评论,并且大文件的每一行为 250 个字符,文件大小为 10 GB。
你没有提到你可能有多少种模式。所以我进行了测试,似乎内联完成的 sed 命令在 50 个模式之前的某个地方分崩离析。
(当然,如果您的样本确实是数据的样子,那么您可以根据非 AGCT 而不是基于模式文件对每一行进行修剪。这会更快)
但基于原始问题。您可以根据 patterns.txt 在单独的文件中生成 sed 脚本。像这样:
sed -e "s/^/s\//g;s/$/.*\$\/\/g/g;" patterns.txt > temp.sed
然后在 sed 命令上使用这个临时文件。
grep -f patterns.txt -m 5 bigtext.txt | sed -f temp.sed
grep 在找到 X 个匹配项后停止,sed 修剪那些...新功能在几秒钟内在我的机器上运行。为了测试,我创建了一个包含 250 个字符的 AGCT 组合的 2GB 文件。另一个包含 50 多个模式的文件,每个 120 个字符,其中一些模式取自 bigtext 文件的随机行。
function findMatches() {
sed -e "s/^/s\//g;s/$/.*\$\/\/g/g;" patterns.txt > temp.sed
grep -f patterns.txt -m ${1:-5} bigtext.txt | sed -f temp.sed
}
推荐阅读
- reactjs - 在通过孩子时反应 forceUpdate
- java - 正则表达式除某些字母数字字符和最大数字序列外的任何字母数字字符
- gitlab - 我可以使用 Webhook 将用户添加到 Gitlab 私人组吗?
- javascript - 未找到 react-native-svg ForeignObject 元素(React-Native + Expo + TypeScript)
- javascript - 如何为 jsPDF 调整画布的大小
- c - 刽子手游戏错误
- javascript - Webpack 环境变量是未知参数
- python - 应用于列时,带有 lambda 函数的 Pandas 数据框错误
- c# - 轮廓的 arcLength 的结果是什么?
- python - 无法导入名称 getoutput