有关我工作环境的信息:
$ 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相同的结果而不将我的部分代码放在第二行吗?
提前谢谢
答案 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($'...'
)的单行解决方案,这是合适的,因为您最初标记了你的问题bash
(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} }序列。