Sed没有写入文件

时间:2016-02-26 19:35:04

标签: linux bash awk sed cat

我想简单地更改CSV上的分隔符。 该文件来自外部服务器,因此分隔符是这样的:^ A。

name^Atype^Avalue^A
john^Ab^A500
mary^Ac^A400
jack^Ad^A200

我想得到这个:

name,type,value
john,b,500
mary,c,400
jack,d,200

我需要将其更改为逗号(,)或制表符(,),但我的sed命令,尽管输出正确,但不会写入文件。

cat -v CSVFILE | sed -i "s/\^A/,/g"

当我使用上面的行时,它正确输出用逗号分隔的文件而不是^ A,但它不会写入文件。

我也尝试过这样:

sed -i "s/\^A/,/g" CSVFILE

也不起作用...... 我做错了什么?

4 个答案:

答案 0 :(得分:2)

  • 文字 ^A(两个字符,^A)是cat -v 可视化的方式< / em>控制字符0x1 (ASCII代码1,名为SOH(标题的开头))。 ^Acaret notation代表不可打印的ASCII字符的示例:

    • ^A代表键盘组合 Control-A ,当前面是通用转义序列 Control-V 时,就是如何创建终端中的实际控制字符;换句话说,
      Control-V Control-A 将插入一个实际的0x1字符。

    • 顺便说一句,插入符号(^<letter>)的逻辑是:字母对应于所表示的控制字符的ASCII值;例如,A对应0x1D对应0x4^DEOT)。
      换句话说:将0x40添加到控制字符的ASCII值中,以符号表示法获取其字母表示的ASCII值。
      ^@代表NUL0x0字符)而^?代表DEL0x7f)与此符号一致,因为{{1}具有ASCII值@(即,它出现在ASCII表中的0x40A之前)并且0x41约束为7位(与...进行位与运算)最大ASCII值0x40 + 0x7f)产生0x7f,这是0x3f的ASCII值。

    • 检查给定文件中<异或控制字符的 ASCII值 ,您可以将其管道传输到? ,表示od -c为(八进制)0x1

  • 这意味着直接将文件传递给001 时,您不能使用插入符号,而必须使用实际控制字符sed来电中的<>

    • 请注意,当您使用 Control-V Control-A 创建实际 s字符时,它还会< em>以插入符号表示 - 作为0x1 - 但在这种情况下,它只是终端对真实控制字符的可视化;虽然它可能看起来像两个可打印的字符^A^,但它不是。纯粹在视觉上你无法区分 - 这就是为什么使用转义序列或ANSI C引用的字符串来表示控制字符是更好的选择 - 见下文。
  • 假设您的shell为Abashksh,则更好的替代方法是使用 Control-V Control-A 使用ANSI C-quoted string生成zsh字符:0x1

    • 但是,正如Lars Fischer在对该问题的评论中指出的那样, GNU $'\1'也会识别sed的转义序列\x01 。< / LI>

因此,您的命令应该是:

0x1

或使用ANSI C引用的字符串:

sed -i 's/\x01/,/g' CSVFILE    # \x01 only recognized by GNU sed

注意:虽然此表单原则上可以与 BSD / OSX sed -i $'s/\1/,/g' CSVFILE 一起使用,但sed语法略有不同:您必须使用-i

使用sed -i '' $'s/\1/,/g' CSVFILE执行任务的唯一原因是利用就地更新(sed);否则,-i是更好的选择 - 请参阅Ed Morton's answer

答案 1 :(得分:1)

如果您的sed支持-i选项,则可以像这样使用它:

sed -i.bak -e "s/\^A/,/g" CSVFILE

(这假定源文件中的分隔符由两个字符^和A组成;如果^ A应该引用Control-A,则必须相应地进行调整,例如使用's/\x01/,/g'。 )

否则,假设您要保留原始文件的副本(例如,如果结果不符合您的预期 - 请参阅下文),可以使用以下咒语:

mv CSVFILE CSVFILE.bak  &&  sed "s/\^A/,/g" CSVFILE.bak > CSVFILE

正如其他地方所指出的,如果源文件分隔符是Control-A,您还可以使用tr '\001' ,(或tr '\001' '\t'作为标签页。)

需要注意的是,源文件中的分隔符可能会被精确使用,因为逗号可能出现在&#34;值&#34;分隔符是分开的。如果这是可能的话,那么将需要一种不同的方法。 (参见例如https://tools.ietf.org/html/rfc4180

答案 2 :(得分:1)

这是创建的作业tr

tr '<control-A>' ',' < file > tmp && mv tmp file

显然用文字控件-A替换<control-A>

答案 3 :(得分:0)

如果它在OS X下运行:

  • -i添加扩展程序以写入新文件:

    sed -i.bak "s/^A/,/g" CSVFILE
    
  • 或写到位:

    sed -i '' "s/^A/,/g" CSVFILE
    
  • 您也可以使用cat输出到文件但在sed上没有-i 命令:

    cat -v CSVFILE | sed "s/^A/,/g" > ouput
    

确保以这种方式写^ A:

控制 + V + 控制 + A