2014-05-16 47 views
5

我想在字符串中第二次出现特定 模式后删除所有内容。在Unix中做这件事的最好方法是什么?什么是最优雅和简单的方法来实现这一点; sed,awk或只是像cut unix命令?第二次发生后,在unix中的字符串中删除所有内容

我的投入将是

After-u-math-how-however 

输出应该是

After-u 

一切后第-应该被剥离出来。正则表达式也应该匹配 模式的零次出现,所以应该忽略零次或一次出现,并且应该从第二次出现中删除所有内容。

所以,如果输入的是如下

 
After 

输出应该是

 
After 

回答

8

怎么这样呢?

echo "After-u-math-how-however" | cut -f1,2 -d'-'

+0

看起来最棒! 关于如何在sed或awk中获得相同的任何想法? – Jose

0
awk '$0 = $2 ? $1 FS $2 : $1' FS=- 

结果

 
After-u 
After 
0

这将做,在AWK:

echo "After" | awk -F "-" '{printf "%s",$1; for (i=2; i<=2; i++) printf"-%s",$i}' 
+0

好吧,我还有另一个裂缝。尽管我有更好的判断力,因为OP没有做任何研究,也没有做任何解决的尝试。 –

1

这可以以纯的bash进行(这意味着没有叉,没有外部的过程)。读入的数组分割 ' - ',然后切片的数组:

$ IFS=- 
$ read -ra val <<< After-u-math-how-however 
$ echo "${val[*]}" 
After-u-math-how-however 
$ echo "${val[*]:0:2}" 
After-u 
+1

好的解决方案。不过,你应该重置IFS吗? –

+0

@EvanPurkhiser不,你应该使用范围来管理价值。把上面的代码放在一个带有'local IFS'的函数中,而不是试图手动保存和恢复原来的IFS。 – kojiro

+2

所以对此的肯定是没有fork,没有外部进程(为什么我们在意?)但是否定的是,您仍然需要编写更多代码来管理IFS更改的范围,如果您想要在多于1行的行上执行此操作需要手动编写一个循环来处理每行(与sed和awk解决方案不同),并且正确地写入它会错误地处理输入中的任何反斜杠,此外您还需要考虑是否存在符合条件的影响,再加上你需要考虑回声是否会按照预期行事。 Shell是一个可以调用工具的环境。 –

2

您可以使用下面的正则表达式来选择你想要什么:

^[^-]*-\?[^-]* 

例如:

echo "After-u-math-how-however" | grep -o "^[^-]*-\?[^-]*" 

结果:

After-u 
+0

+1;但请注意,FreeBDS grep 2.5.1(例如OS X 10.9.3)似乎存在_bug_,导致忽略“^”锚点,从而导致潜在的_multiple_匹配(从而导致多个输出线)。在GNU'grep'下正常工作。 – mklement0

1
awk -F - '{print $1 (NF>1? FS $2 : "")}' <<<'After-u-math-how-however' 
  • 根据字段分隔符-(选项规范)将行拆分为字段。 -F -) - 可作为特殊变量FS内部awk程序。
  • 始终打印的第一场(print $1),其次是:
    • 如果有超过1场NF>1),追加FS(即,-)和第二场($2
    • 否则:追加"",即:有效地仅打印第一字段(其本身可以是空的,如果输入是空的)。
2

这可能会为你工作(GNU SED):

sed 's/-[^-]*//2g' file 
2

@ EvanPurkisher的cut -f1,2 -d'-'解决方案恕我直言最好的之一,但既然你问的sed和awk:

随着GNU sed for -r

$ echo "After-u-math-how-however" | sed -r 's/([^-]+-[^-]*).*/\1/' 
After-u 

With GNU awk的对gensub()

$ echo "After-u-math-how-however" | awk '{$0=gensub(/([^-]+-[^-]*).*/,"\\1","")}1' 
After-u 

可与非GNU进行使用\(*,并与非GNU AWK的Sed使用match()substr()如果必要的。

+1

+1为'sed'解决方案;使用'-E'而不是'-r'会使命令与GNU(Linux)和BSD(OSX)'sed'一起工作。 POSIX'sed',它使用_basic_ regexes,_can_模拟'+',即'\ {1,\}':'sed's/\([^ - ] \ {1,\} - [^ - ] * \)。*/\ 1 /'' – mklement0

相关问题