b / w下面有两个sed命令有什么区别?

时间:2016-03-25 20:20:50

标签: regex unix sed ksh aix

有关我工作环境的信息:

$ uname -a  
AIX prd231 1 6 00C6B1F74C00  
$ oslevel -s  
6100-03-10-1119

代码块A

( grep schdCycCleanup $DCCS_LOG_FILE | sed 's/[~]/ \
/g' | grep 'Move(s) Exist for cycle' | sed 's/[^0-9]*//g' ) > cycleA.txt

代码块B

( grep schdCycCleanup $DCCS_LOG_FILE | sed 's/[~]/ \n/g' | grep 'Move(s) Exist for cycle' | sed 's/[^0-9]*//g' ) > cycleB.txt

我有两个代码块(如上所示),它们使用sed将输入修剪为6位数,但是一个命令的行为与我预期的不同。

两个代码块的输入示例

Mar 25 14:06:16 prd231 ajbtux[33423660]: 20160325140616:~schd_cem_svr:1:0:SCHD-MSG-MOVEEXISTCYCLE:200705008:AUDIT:~schdCycCleanup - /apps/dccs/ajbtux/source/SCHD/schd_cycle_cleanup.c - line 341~ SCHD_CYCLE_CLEANUP - Move(s) Exist for cycle 389210~

当上面的示例输入通过两个代码块时,我得到以下输出。

cycleA.txt内容

389210

cycleB.txt内容

25140616231334236602016032514061610200705008341389210

据我所知,我的最后一个管道sed命令(sed's / [^ 0-9] * // g')正在删除除数字以外的所有字符,所以我从块代码中省略了它,并将输出放在另外两个文件。我得到以下输出。

cycleA1.txt内容

 SCHD_CYCLE_CLEANUP - Move(s) Exist for cycle 389210

cycleB1.txt内容

Mar 25 15:27:58 prd231 ajbtux[33423660]: 20160325152758: nschd_cem_svr:1:0:SCHD-MSG-MOVEEXISTCYCLE:200705008:AUDIT: nschdCycCleanup - /apps/dccs/ajbtux/source/SCHD/schd_cycle_cleanup.c - line 341 n SCHD_CYCLE_CLEANUP - Move(s) Exist for cycle 389210 n

我可以看到第一个代码块正在删除其他所有东西(SCHD_CYCLE_CLEANUP - Move(s)Exist for cycle 389210)并且正在使用波浪号,但第二个代码块只是用字符n替换波浪号。我还可以看到在第一个代码块中有必要在此之后进行换行(sed's / [〜] /),这就是为什么我会用\ n来模拟换行符但事实并非如此。我认为我的输出结果不同是因为正则表达式的使用方式。我试图查看正则表达式并在stackoverflow上搜索它们但没有获得我正在寻找的东西。有人可以解释一下如何从代码块B中获得与代码块A相同的结果而不将我的部分代码放在第二行吗?

提前谢谢

3 个答案:

答案 0 :(得分:5)

这是XY问题的一个例子(http://xyproblem.info/)。您正在寻求帮助来实施一些错误解决问题的方法。为什么在给出所发布的样本输入和预期输出所需的全部内容时,将~更改为换行符等等:

$ sed -n 's/.*schdCycCleanup.* \([0-9]*\).*/\1/p' file
389210

或:

$ awk -F'[ ~]' '/schdCycCleanup/{print $(NF-1)}' file
389210

如果这不是您所需要的,请编辑您的问题以澄清您对 WHAT 的要求(而不是您尝试这样做),因为您当前的方法只是错。

答案 1 :(得分:2)

GNU sed处理\n替换方式。

OS X(可能是BSD)sed没有。它将其视为正常的转义角色,并将其转移到n。 (虽然我目前在任何地方都没有看到这个。)

如果您愿意,可以使用$''引号将\n用作文字换行符。

echo 'foo~bar~baz' | sed $'s/[~]/\\\n/g'

答案 2 :(得分:2)

Etan Reisner's helpful answer解释了问题并提供了基于ANSI C-quoted string$'...')的单行解决方案,这是合适的,因为您最初标记了你的问题 Ed Morton's helpful answer向您展示如何绕过您的问题与不同的方法,这既简单又高效。)

然而,听起来你的shell实际上是不同的东西 - 大概是ksh88,是旧版本的Korn shell,它是AIX 6.1上的默认sh - 其中这些字符串是支持 [1]  (ANSI C引用的字符串在ksh93中引入,不仅在bash中受支持,在zsh中也受支持。

因此,您有以下选项

  • 使用当前的shell,您必须坚持使用两行解决方案,其中包含(\ - 转义的)实际换行符,与代码块A中一样。

    • 请注意,创建新行的$(printf '\n') 有效,因为命令替换总是会修剪所有尾随换行符,在这种情况下会导致为空字符串。
  • 使用支持ANSI C引用字符串的更现代的shell ,并使用Etan的答案。 http://www.ibm.com/support/knowledgecenter/ssw_aix_61/com.ibm.aix.cmds3/ksh.htm告诉我ksh93 在AIX 6.1上作为备用shell提供,/usr/bin/ksh93

  • 如果可行:安装 GNU sed ,它本身可以理解转义序列,例如替换字符串中的\n

[1]至于在类似POSIX的shell中尝试echo 'foo~bar~baz' | sed $'s/[~]/\\\n/g'支持$'...'时实际发生的情况:{{1} }保留原样,因为后面的内容不是有效的变量名称,$最终会看到文字sed,其中$s/[~]/\\\n/g被解释为应用于<的上下文地址em> last 输入行 - 这里没有区别,因为只有 1 行。 $被解释为普通\\\被解释为普通\n,有效地将n个实例替换为 literal {{1} }序列。

相关问题