如何从文本文件的行中删除特定单词?

O.E*_*O.E 13 command-line text-processing

我的文本文件如下所示:

Liquid penetration 95% mass (m) = 0.000205348
Liquid penetration 95% mass (m) = 0.000265725
Liquid penetration 95% mass (m) = 0.000322823
Liquid penetration 95% mass (m) = 0.000376445
Liquid penetration 95% mass (m) = 0.000425341
Run Code Online (Sandbox Code Playgroud)

现在我想Liquid penetration 95% mass (m)从我的行中删除以仅获取值。我该怎么做?

Zan*_*nna 22

如果只有一个=标志,您可以删除之前和包括的所有内容,=如下所示:

$ sed -r 's/.* = (.*)/\1/' file
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341
Run Code Online (Sandbox Code Playgroud)

如果要更改原始文件,请-i在测试后使用该选项:

sed -ri 's/.* = (.*)/\1/' file
Run Code Online (Sandbox Code Playgroud)

笔记

  • -r使用ERE所以我们没有逃避()
  • s/old/new替换oldnew
  • .* 任意数量的任意字符
  • (things)保存things迟些反向引用\1\2等等。


hee*_*ayl 21

这是一份工作awk;假设值仅出现在最后一个字段中(根据您的示例):

awk '{print $NF}' file.txt
Run Code Online (Sandbox Code Playgroud)
  • NF是一个awk变量,扩展为记录(行)中的字段数,因此$NF(注意$前面的)包含最后一个字段的值。

例子:

% cat temp.txt 
Liquid penetration 95% mass (m) = 0.000205348
Liquid penetration 95% mass (m) = 0.000265725
Liquid penetration 95% mass (m) = 0.000322823
Liquid penetration 95% mass (m) = 0.000376445
Liquid penetration 95% mass (m) = 0.000425341

% awk '{print $NF}' temp.txt
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341
Run Code Online (Sandbox Code Playgroud)


pa4*_*080 15

我决定比较这里列出的不同解决方案。为此,我根据 OP 提供的内容创建了一个大文件:

  1. 我创建了一个简单的文件,名为input.file

    $ cat input.file
    Liquid penetration 95% mass (m) = 0.000205348
    Liquid penetration 95% mass (m) = 0.000265725
    Liquid penetration 95% mass (m) = 0.000322823
    Liquid penetration 95% mass (m) = 0.000376445
    Liquid penetration 95% mass (m) = 0.000425341
    
    Run Code Online (Sandbox Code Playgroud)
  2. 然后我执行了这个循环:

    for i in {1..100}; do cat input.file | tee -a input.file; done
    
    Run Code Online (Sandbox Code Playgroud)
  3. 终端窗口被阻止。我killall tee从另一个终端执行。然后我通过命令检查了文件的内容:less input.filecat input.file。看起来不错,除了最后一行。所以我删除了最后一行并创建了一个备份副本:(cp input.file{,.copy}因为使用inplace选项的命令)。

  4. 文件中的最终行数input.file2 192 473。我通过命令得到了那个号码wc

    $ cat input.file | wc -l
    2192473
    
    Run Code Online (Sandbox Code Playgroud)

这是比较的结果:

  • grep -o '[^[:space:]]\+$'

    $ time grep -o '[^[:space:]]\+$' input.file > output.file
    
    真正的 0m58.539s
    用户 0m58.416s
    系统 0m0.108s
    
  • sed -ri 's/.* = (.*)/\1/'

    $ time sed -ri 's/.* = (.*)/\1/' input.file
    
    真正的 0m26.936s
    用户 0m22.836s
    系统 0m4.092s
    

    或者,如果我们将输出重定向到新文件,命令会更快:

    $ time sed -r 's/.* = (.*)/\1/' input.file > output.file
    
    真正的 0m19.734s
    用户 0m19.672s
    系统 0m0.056s
    
  • gawk '{gsub(".*= ", "");print}'

    $ time gawk '{gsub(".*= ", "");print}' input.file > output.file
    
    真正的 0m5.644s
    用户 0m5.568s
    系统 0m0.072s
    
  • rev | cut -d' ' -f1 | rev

    $ time rev input.file | 剪切 -d' ' -f1 | rev > output.file
    
    真正的 0m3.703s
    用户 0m2.108s
    系统 0m4.916s
    
  • grep -oP '.*= \K.*'

    $ time grep -oP '.*= \K.*' input.file > output.file
    
    真正的 0m3.328s
    用户 0m3.252s
    系统 0m0.072s
    
  • sed 's/.*= //' (该-i选项分别使命令慢了几倍)

    $ time sed 's/.*= //' input.file > output.file
    
    真正的 0m3.310s
    用户 0m3.212s
    系统 0m0.092s
    
  • perl -pe 's/.*= //' (该-i选项不会对此处的生产力产生太大影响)

    $ time perl -i.bak -pe 's/.*= //' input.file
    
    真正的 0m3.187s
    用户 0m3.128s
    系统 0m0.056s
    
    $ time perl -pe 's/.*= //' input.file > output.file
    
    真正的 0m3.138s
    用户 0m3.036s
    系统 0m0.100s
    
  • awk '{print $NF}'

    $ time awk '{print $NF}' input.file > output.file
    
    真正的 0m1.251s
    用户 0m1.164s
    系统 0m0.084s
    
  • cut -c 35-

    $ time cut -c 35- input.file > output.file
    
    真实 0m0.352s
    用户 0m0.284s
    系统 0m0.064s
    
  • cut -d= -f2

    $ time cut -d= -f2 input.file > output.file
    
    真实 0m0.328s
    用户 0m0.260s
    系统 0m0.064s
    

想法的来源。

  • 所以 [我的`cut -d= -f2` 解决方案](https://askubuntu.com/a/968035/283843) 获胜。哈哈 (2认同)

αғs*_*нιη 12

grep-P用于具有PCRE(解读图案作为P ERL- Ç ompatible ř egular È XPRESSION)和-o打印匹配的单独模式。该\K通知会忽略自己之前所匹配的部分来了。

$ grep -oP '.*= \K.*' infile
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341
Run Code Online (Sandbox Code Playgroud)

或者你可以改用cut命令。

cut -d= -f2 infile
Run Code Online (Sandbox Code Playgroud)

  • 除了在 [pa4080 的基准测试](https://askubuntu.com/a/968178/22949) 中测试的所有方法中运行最快之外,**这个答案中的 `cut` 方法**在 [我运行的一个较小的基准测试](https://askubuntu.com/a/968771/22949) 测试了较少的方法,但使用了较大的输入文件。它比我个人喜欢的方法的快速变体快十倍以上(我的答案主要是关于)。 (2认同)

Dav*_*ter 11

由于行前缀始终具有相同的长度(34 个字符),您可以使用cut

cut -c 35- < input.txt > output.txt
Run Code Online (Sandbox Code Playgroud)


小智 6

使用 反转文件的内容rev,将输出通过管道传输到cut以空格作为分隔符和 1 作为目标字段,然后再次反转以获取原始数字:

$ rev your_file | cut -d' ' -f1 | rev
0.000205348
0.000265725
0.000322823
0.000376445
0.000425341
Run Code Online (Sandbox Code Playgroud)


Eli*_*gan 5

这很简单,简短,易于编写、理解和检查,我个人喜欢它:

grep -oE '\S+$' file
Run Code Online (Sandbox Code Playgroud)

grep在 Ubuntu 中,当用-Eor调用时-P,使用速记 \s表示空白字符(实际上通常是空格或制表符)并\S表示任何不是一个的东西。使用量词+行尾锚点$模式\S+$匹配一行末尾的一个或多个非空白。您可以使用-P代替-E这种情况下的含义是相同的,但使用了不同的正则表达式引擎,因此它们可能具有不同的性能特征

这相当于Avinash Raj 的评论解决方案(只是使用更简单、更紧凑的语法):

grep -o '[^[:space:]]\+$' file
Run Code Online (Sandbox Code Playgroud)

如果数字后面可能有尾随空格这些方法将不起作用。他们可以修改,所以他们这样做,但我认为在这里没有意义。尽管将解决方案概括为适用于更多情况有时是有益的,但像人们倾向于假设的那样经常这样做并不切实际,因为人们通常无法知道问题最终可能需要以多种不同的不兼容方式中的哪一种来解决被概括。


性能有时是一个重要的考虑因素。这个问题并没有规定输入非常大,很可能这里发布的每个方法都足够快。但是,如果需要速度,这里有一个关于一千万行输入文件的小基准:

$ perl -e 'print((<>) x 2000000)' file > bigfile
$ du -sh bigfile
439M    bigfile
$ wc -l bigfile
10000000 bigfile
$ TIMEFORMAT=%R
$ time grep -o '[^[:space:]]\+$' bigfile > bigfile.out
819.565
$ time grep -oE '\S+$' bigfile > bigfile.out
816.910
$ time grep -oP '\S+$' bigfile > bigfile.out
67.465
$ time cut -d= -f2 bigfile > bigfile.out
3.902
$ time grep -o '[^[:space:]]\+$' bigfile > bigfile.out
815.183
$ time grep -oE '\S+$' bigfile > bigfile.out
824.546
$ time grep -oP '\S+$' bigfile > bigfile.out
68.692
$ time cut -d= -f2 bigfile > bigfile.out
4.135
Run Code Online (Sandbox Code Playgroud)

我运行了两次以防顺序很重要(因为它有时会处理 I/O 繁重的任务),并且因为我没有一台可用的机器在后台不做其他可能会扭曲结果的事情。从这些结果中,我得出以下结论,至少是暂时的,对于我使用的大小的输入文件:

  • 哇!传递-P(使用PCRE)而不是-G(未指定方言时的默认值)或-E使grep速度提高一个数量级以上。所以对于大文件,使用这个命令可能比上面显示的更好:

    grep -oP '\S+$' file
    Run Code Online (Sandbox Code Playgroud)
  • 哇!!cut在方法?的???的答案,是在一个数量级,甚至比速度更快的版本我的方式更快!它也是pa4080 基准测试的赢家,它涵盖了比这更多的方法,但输入更少——这就是为什么我在所有其他方法中选择它来包含在我的测试中。如果性能很重要或文件很大,我认为应该使用??s??? 的方法cut -d= -f2 filecut

    这也提醒我们不应忘记简单cutpaste实用程序,并且在适用时可能应该首选,即使有更复杂的工具grep通常作为一线解决方案提供(而且我个人更习惯)使用)。