ter*_*don 9 sed awk perl text-processing
如何从命令行操作基于字段的数据?例如
foo?foo?foo?foo?是否有标准方法或工具集有助于在 *nix 系统上操作基于字段的数据?
处理字段时可以使用两种基本方法:i) 使用理解字段的工具;ii) 使用正则表达式。在这两者中,前者通常更加健壮和简单。
*nix 上的许多常用工具要么是明确设计来处理字段的,要么有一些巧妙的技巧来促进它。
这里的经典工具是awk. 它会自动分割每个输入线成字段(字段分隔符是空白默认但可以使用被改变-F标志)和字段然后提供给awk脚本,其中是场号。第一个字段是,第二个等等。$nn$1$2
打印第 3 个字段为 的行foo。
awk '$3=="foo"' file
Run Code Online (Sandbox Code Playgroud)
将分隔符更改为 :
awk -F":" '$3=="foo"' file
Run Code Online (Sandbox Code Playgroud)
的默认操作awk是打印。因此,上面的命令将打印第三个字段为foo. 使用时-F,可以设置任意字段分隔符,甚至可以使用正则表达式。
如何仅打印第 3 个字段不是的行foo?
awk '$3!="foo"' file
Run Code Online (Sandbox Code Playgroud)如何仅打印第 3 个字段匹配的行foo?
如果您只是在寻找与模式匹配的字段(例如,foomatches foobar),请使用~代替==:
awk '$3~/foo/' file
Run Code Online (Sandbox Code Playgroud)如何仅打印第 3 个字段不匹配的行foo?
awk '$3!~/foo/' file
Run Code Online (Sandbox Code Playgroud)如何将第三个字段更改为foo?
awk '$3="foo"' file
Run Code Online (Sandbox Code Playgroud)另一种选择是perl单线。与 awk 一样,Perl 是一种功能齐全的脚本语言,但也可以作为以脚本为输入的命令行程序运行。它的行为由命令行开关修改,其中与此问题最相关的是:
-e:perl应该运行的脚本;-n : 逐行读取输入文件;-p: 在应用给定的脚本后打印每个输入行-e;-l: 从每个输入行中删除尾随换行符,并为每个print调用添加一个换行符;-a: awk-mode,将每条输入行拆分成数组@F;-F: 的字段分隔符-a。与 的一个重要区别awk是 thatperl的-a开关将文件拆分为一个数组。在 Perl 中,数组从 0 开始,而不是 1。这意味着第二个字段实际上是$F[1]而不是$F[2]。考虑到所有这些,perl上面的等价物是:
打印第 3 个字段为 的行foo。
perl -ane 'print if $F[2] eq "foo"' file
Run Code Online (Sandbox Code Playgroud)
将分隔符更改为 :
perl -F":" -ane 'print if $F[2] eq "foo"' file
Run Code Online (Sandbox Code Playgroud)
与 不同awk,perl不能使用正则表达式作为字段分隔符。它们需要是特定的字符或字符串。
如何仅打印第 3 个字段不是的行foo?
perl -ane 'print unless $F[2] eq "foo"' file
Run Code Online (Sandbox Code Playgroud)如何仅打印第 3 个字段匹配的行foo?
perl -ane 'print if $F[2]=~/foo/' file
Run Code Online (Sandbox Code Playgroud)如何仅打印第 3 个字段不匹配的行foo?
perl -lane 'print unless $F[2]=~/foo/' file
Run Code Online (Sandbox Code Playgroud)如何将第三个字段更改为foo?
这个在 Perl 中有点麻烦。通常的做法是改变@F数组中的值,然后打印数组。使用简单的空格分隔文件,这很容易:
perl -lane '$F[2]="foo"; print "@F"' file
Run Code Online (Sandbox Code Playgroud)
使用不同的分隔符,您将需要join数组。否则,它将以空格分隔打印:
perl -F: -lane '$F[2]="foo"; print join ":",@F' file
Run Code Online (Sandbox Code Playgroud)这里的想法是使用正则表达式(简称“regex”)来定义目标字符串在行中的位置。例如,在一个字段由 分隔的文件中:,我们可以通过匹配直到第一个:(第一个字段)的所有内容,然后查找第二个字段来找到第二个字段:
^[^:]*:[^:]*:
Run Code Online (Sandbox Code Playgroud)
这个正则表达式的意思是:
^ : 行首;[^]: 否定字符类。[^:]意思是“除了”之外的任何东西:;* : 0 个或多个前一个模式;:: 字面意思:;综合起来,这意味着第一个[^:]*是第一个字段,第二个是第二个字段。显然,如果您正在寻找第 14 个字段,这不是很实用,但它对于更简单的事情很有用。那么,我们如何实现它来操纵我们的数据呢?有多种工具可以做到这一点;在这些示例中,我将使用,sed但您可以使用awk,perl或做非常相似的事情python。
如何仅打印第二个字段为 的行foo?
sed -n '/^[^:]*:foo:/p' file
Run Code Online (Sandbox Code Playgroud)
所述-n禁止显示正常输出和/regex/p装置“打印正则表达式匹配的任何行。
如何仅打印第二个字段不是的行foo?
sed '/^[^:]*:foo:/d' file
Run Code Online (Sandbox Code Playgroud)
上面的逻辑逆。在这里,/regex/d意思是“删除正则表达式匹配的任何行。
如何仅打印第二个字段匹配的行foo?
sed -n '/^[^:]*:[^:]*foo/p' file
Run Code Online (Sandbox Code Playgroud)如何仅打印第二个字段不匹配的行foo?
sed '/^[^:]*:[^:]*foo/d' file
Run Code Online (Sandbox Code Playgroud)如何将第二个字段更改为foo?
sed 's/\([^:]*:\)[^:]*/\1foo/' file
Run Code Online (Sandbox Code Playgroud)
或者,由于sed替换可以通过使用简单的数字标志重复来直接解决模式发生的问题:
sed 's/[^:]*/foo/2' file
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
1600 次 |
| 最近记录: |