使用shell脚本将文件输入格式化为所需的输出

时间:2015-09-24 03:17:28

标签: bash shell unix awk sh

我需要将给定输入格式化为显示的输出。我该怎么办?

输入:

\n    \abc\:\abc_2\,\n    \rick\:\rick_1\,\n    \harry\:\harry_1\,\n    \Christine\:\Christine_2\,\n

enter image description here

2 个答案:

答案 0 :(得分:1)

如果数据到达带有反斜杠的单行,那么我认为你可以稍微小心地使sed工作。

  • 您需要使用换行符替换每个\,序列。
  • 您需要替换每个\n,然后替换为零或多个空格。
  • 您需要用任何内容替换每个剩余的反斜杠。
  • 您需要删除最终换行符(因此您不会有两个换行符。)

转换为:

echo '\n    \abc\:\abc_2\,\n    \rick\:\rick_1\,\n    \harry\:\harry_1\,\n    \Christine\:\Christine_2\,\n' |
sed -e 's/\\,/\n/g' \
    -e 's/\\n *//g' \
    -e 's/\\//g' \
    -e 's/\n$//'

当我使用GNU sed时,这对我来说正常。它没有产生正确的'输出BSD(Mac OS X)sed;我没有在输出中插入换行符。这是因为BSD sed符合POSIX sed规范,该规范说:

  

转义序列&#39; \n&#39;应匹配模式空间中嵌入的<newline>。文本<newline>不得用于上下文地址或替代函数的BRE中。

Mac OS X上sed的手册页大致相同:

  

转义序列\n匹配嵌入在模式空间中的换行符。但是,您不能在地址或替换命令中使用文字换行符。

你怎么解决这个问题?痛苦的,可能就是答案。可以使用y命令,因为POSIX说:

  

[2addr] y/string1/string2/
      将 string1 中出现的所有字符替换为 string2 中的相应字符。如果<backslash>后跟'n' string1 string2 中显示[sic],则这两个字符应作为单个{{1}处理}}。如果 string1 string2 中的字符数不相等,或者 string1 中的任何字符出现多次,则结果为未定义。可以使用<newline><backslash>以外的任何字符代替<newline>来分隔字符串。如果分隔符不是 string1 string2 中的分隔符,则分隔符本身可以用作文字字符(如果前面有{ {1}}。如果 string1 string2 中的<slash>字符后面紧跟<backslash>字符,则两个<backslash>字符应计为单个文字<backslash>字符。 <backslash>后跟任何不是&#39; n&#39;,<backslash>或分隔符的字符的含义是未定义的。

Mac OS X手册页不那么冗长,也不那么迂腐精确,但大致相同。所以,我认为诀窍是将<backslash>映射到 Control-A 等字符,然后使用<backslash>映射 Control-A 到换行符。

那是:

\,

(显示为y/^A/\n/的实际上是 Control-A ;我需要使用 Control-V Control-A echo '\n \abc\:\abc_2\,\n \rick\:\rick_1\,\n \harry\:\harry_1\,\n \Christine\:\Christine_2\,\n' | sed -e 's/\\,/^A/g' \ -e 'y/^A/\n/' \ -e 's/\\n *//g' \ -e 's/\\//g' \ -e 's/\n$//' 中输入字符。)无论如何,这适用于Mac OS X或BSD ^A

答案 1 :(得分:1)

使用GNU awk进行多字符RS:

$ awk -v RS=',?\\\\n[[:space:]]+' 'gsub(/\\/,"")' file
abc:abc_2
rick:rick_1
harry:harry_1
Christine:Christine_2