4

我尝试了一些事情,但似乎没有取得任何进展 - 我有一个包含一些数据行的文本文件,我想要该文件中的一些数据行。每行都有一个唯一的标识符,我可以 grep。

如果我使用

grep 'name1\|name2\|name3\|name4' file.txt > newfile.txt

它完成了工作并 greps 我想要的所需行,但是,我想要按照我指定的顺序排列的行 - 在这个例子中,我首先想要 name1 行,然后是 name2 行,然后是 name3 行,最后是 name4 行。

但是,例如在我的原始文件中,行的顺序是 name2,然后是 name4,然后是 name3,然后是 name1,输出文件似乎也有这个顺序的行。

有没有办法轻松订购 grep?

id 是按块排序的,因此所有带有 name1 的行都彼此相邻。

感谢您的任何建议!

4

5 回答 5

7

使用循环从文件中读取单词

给定一个要 grep 的单词文件,如下所示:

root
lp
syslog
nobody

您可以使用读取循环重复 grep 以获取另一个文件中的固定字符串。例如,使用 Bash shell 的默认REPLY变量和存储在/tmp目录中的 word 文件,这将起作用:

while read; do
    grep --fixed-strings "$REPLY" /etc/passwd
done < /tmp/words

笔记

  1. 发布的示例不会阻止多个匹配,但它将确保按照定义的顺序进行匹配/tmp/words
  2. 出于性能原因,该示例使用 GNU grep 和固定字符串。您的里程可能会因其他 grep 和正则表达式而异。
于 2013-09-04T17:41:47.393 回答
1

您可以使用 awk 数组。

awk 'BEGIN { k[1]="name1"; k[2]="name2"; k[3]="name3" }
{ for (i=1; i<4; ++i) if ($0 ~ k[i]) m[i]=(m[i]?m[i] RS:"") $0 }
END { for(i=1; i<4; ++i) if (m[i]) print m[i] }' file

如果一行匹配多个表达式,这将产生重复。如果您需要快速,可以对其进行一些优化;问一下。

或者在 Perl 中:

perl -ne 'BEGIN { @k = qw( name1 name2 name3 name4 );
    $k = join("", "(", join("|", @k), ")");
    $r = qr($k); }
  if(m/$r/) { push @{$m{$1}}, $_ }
  END { for $i (@k) { if ($m{$i}) {
    print join("", @{$m{$i}}); } } }' file

这可能比等效的 awk 脚本更有效。它每行只能找到一个匹配项,因此它并不完全等价。

于 2013-09-04T18:11:57.100 回答
0

一个蹩脚的解决方案可能是.. 多次运行 grep 命令(也许您可以将其粘贴到 shell 脚本中并多次运行)

grep 'name1' file.txt > newfile.txt
grep 'name2' file.txt >> newfile.txt
grep 'name3' file.txt >> newfile.txt
grep 'name4' file.txt >> newfile.txt

希望这可以帮助!

于 2013-09-04T17:20:19.430 回答
0

项目清单

我正在寻找相同的命令,但现在我想通了。

第 1 步:为您的 grep 搜索制作文件。只需将 grep 单词粘贴到文件中,一行中粘贴一个 grep 关键字。例如,我制作文件 mySearch.txt。

更多 mySearch.txt

名称2
名称
3
名称1名称4
名称2
名称1

第 2 步:现在使用此命令
grep -Fwf mySearch.txt file.txt>newfile.txt

cat file.txt|grep -Fwf mySearch.txt >newfile.txt

Thais 命令将首先打印所有带有 name2 的行,然后是 name3 等,然后在 newfile.txt 的末尾打印 name1 行。

于 2014-08-06T16:51:50.553 回答
-1

perl 对于这种搜索和打印会更好。

perl -lne '/name1/?push @a,$_:
          (/name2/?push @b,$_:
          (/name3/?push @c,$_:
           /name4/?push @d,$_:next));
          END{print join "\n",@a,@b,@c,@d}' your_file

下面测试:

> cat temp
1 name1
2 name2
3 name3
4 name1
5 name4
6 name2
7 name1
> perl -lne '/name1/?push @a,$_:(/name2/?push @b,$_:(/name3/?push @c,$_:/name4/?push @d,$_:next));END{print join "\n",@a,@b,@c,@d}' temp
1 name1
4 name1
7 name1
2 name2
6 name2
3 name3
5 name4
> 

好问题虽然:)

于 2013-09-05T07:49:07.397 回答