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

What is the difference b/w two sed commands below?

关于我工作环境的信息:

$ 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 trim 输入低至 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。我还可以看到在 this(sed 's/[~]/ ) 之后的第一个代码块中有必要换行,这就是为什么我虽然有 \n 会模拟换行但事实并非如此。我认为我不同的输出结果是因为正则表达式的使用方式。我试图研究正则表达式并在 Whosebug 上搜索它们,但没有得到我想要的东西。有人可以解释我如何从代码块 B 获得与代码块 A 相同的结果,而无需将我的部分代码放在第二行吗?

提前致谢

GNU sed 以您期望的方式处理 \n 替换。

OS X(大概是 BSD)sed 没有。它把它当作一个普通的转义字符,只是将它转义为 n。 (虽然我目前在手册中的任何地方都看不到这一点。)

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

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

explains the problem and offers a single-line solution based on an ANSI C-quoted string ($'...'), which is appropriate, given that you originally tagged your question .
( 向您展示了如何 绕过 您的问题,同时使用 不同的方法 既简单又高效.)

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

因此,您有以下选项

  • 对于当前的 shell,您必须坚持使用包含以下内容的 双行 解决方案一个 (\-escaped) actual 换行符,如代码块 A.

    • 请注意,$(printf '\n') 创建换行符 无效 ,因为命令替换总是 trim 所有尾随换行符,导致 empty string in this case.
  • 使用支持 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-like shell 中尝试 echo 'foo~bar~baz' | sed $'s/[~]/\\n/g' 时实际发生了什么 not 支持 $'...'$ 保持原样,因为后面的不是有效的变量名,sed 最终看到文字 $s/[~]/\\n/g,其中$ 被解释为应用于 last 输入行的上下文地址 - 这在这里没有区别,因为只有 1 行。 \ 被解释为普通的 \,而 \n 被解释为普通的 n,有效地用 文字 替换 ~ 实例 \n序列。

这是 XY 问题的一个例子 (http://xyproblem.info/)。您正在寻求帮助来实施某些对您的问题来说是错误的解决方案。为什么要将 ~s 更改为换行符等,而您只需要给定发布的样本输入和预期输出是:

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

或:

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

如果这不是您所需要的全部,那么请编辑您的问题以阐明您对 WHAT 您正在尝试做的事情(而不是您正在尝试做的事情)的要求你现在的做法是错误的。