使用sed和regex清除文件(删除一些但不是所有换行符)

时间:2016-11-11 14:15:45

标签: regex sed

我有一个文本文件,我想加载到配置单元。它在字符串列中有换行符,因此无法正确加载。从我在网上发现的文件需要进行预处理,并删除所有这些换行符。到目前为止,我已尝试过许多正则表达式,但无济于事。

这是文件:

/biz/1-or-8;5.0;"a bunch of
text
with some

linebreaks in between.";2016-11-03
/biz/1-or-8;2.0;"more

text
here.";2016-10-18

所需的输出应为:

/biz/1-or-8;5.0;"a bunch of text with some linebreaks in between.";2016-11-03
/biz/1-or-8;2.0;"more text here.";2016-10-18

我可以在记事本++中实现这一点,将其用作正则表达式:(\r\n^(?!\/biz\/))+

然而,当我使用sed运行该正则表达式时,它不起作用:

sed -e 's/(\r\n^(?!\/biz\/))+//g' original.csv > clean.csv

6 个答案:

答案 0 :(得分:1)

如上所述,sed不支持(?!\/biz\/)等外观断言。

由于您的输入基本上是记录,因此awk提供了一种方便的解决方案。

使用 GNU awk或Mawk(需要支持多字符输入记录分隔符):

awk -v RS='/biz/' '$1=$1 { print RS $0 }' file
  • RS='/biz/'/biz/将输入拆分为记录(保留变量RS是输入记录分隔符,默认为\n。)

  • $1=$1看似无操作,但实际上重建手头的输入记录($0),规范化任何记录内部的空白运行 - 包括换行符 - 每个单独一个空格,依赖awk的默认字段拆分和输出行为。

    • 此外,由于$1=$1用作模式(有条件),因此作业的结果决定了相关的操作{ ... })为手头的记录执行。
      对于空记录 - 例如隐含的之前的第一个/biz - 赋值返回'',它在布尔上下文中求值为false,因此跳过关联的块
  • { print RS $0 }打印重建的输入记录,前缀为输入记录分隔符; print会自动附加输出记录分隔符ORS,默认为\n

注意:您的代码引用\r\n,即Windows样式的CRLF换行符。由于您尝试使用sed,我相信Windows上可用的Unix实用程序版本可以透明地处理CRLF。
如果您实际上在Unix平台上并且恰好正在处理源自Windows的文件,则需要做更多的工作。

答案 1 :(得分:0)

也许这可以帮到你;

 sed -n '/^\s*$/d;$!{ 1{x;d}; H}; ${ H;x;s|\n\([^\/biz]\)| \1|g;p}'

测试;

$ sed -n '/^\s*$/d;$!{ 1{x;d}; H}; ${ H;x;s|\n\([^\/biz]\)| \1|g;p}' test
/biz/1-or-8;5.0;"a bunch of text with some linebreaks in between.";2016-11-03
/biz/1-or-8;2.0;"more text here.";2016-10-18

答案 2 :(得分:0)

diagnostic不支持外观,sed确实

perl
  • $ perl -0777 -pe 's/(\n^(?!\/biz\/))+//mg' original.csv /biz/1-or-8;5.0;"a bunch oftextwith somelinebreaks in between.";2016-11-03 /biz/1-or-8;2.0;"moretexthere.";2016-10-18 选项会将整个文件作为单个字符串
  • -0777选项允许在多行字符串中使用m个锚点

注意,Unix系统中的行结尾不使用^$,但如果您的输入确实有,请使用OP中指定的\r


使用不同的分隔符以避免必须转义\r\n

/


另一种方法是删除一对双引号之间的所有perl -0777 -pe 's|(\n^(?!/biz/))+||mg' original.csv 个字符

\n
  • $ perl -0777 -pe 's|".*?"|$&=~s/\n//gr|gse' ip.txt /biz/1-or-8;5.0;"a bunch oftextwith somelinebreaks in between.";2016-11-03 /biz/1-or-8;2.0;"moretexthere.";2016-10-18 修饰符允许s匹配多行,.*修饰符允许使用表达式代替字符串替换
  • e允许对匹配的文字$&=~s/\n//gr
  • 执行替换

答案 3 :(得分:0)

awk救援! (具有多字符RS支持)

$ awk -v RS='\n?^/' 'NF{$1=$1; print "/" $0}' file

$ awk -v RS='\n?^/' 'NF{$1="/"$1}NF' file

答案 4 :(得分:0)

创建文件

$ cat biz.awk
{ # read entire input to a string `f' (skips newlines)
    f = f $0 
}

END {
    gsub("[^^]/biz/", "\n/biz/", f) # add a newline to all but the
                                    # first /biz/
    print f
}

$ cat file
/biz/1-or-8;5.0;"a bunch of
text
with some

linebreaks in between.";2016-11-03
/biz/1-or-8;2.0;"more

text
here.";2016-10-18

用法:

awk -f biz.awk file

答案 5 :(得分:0)

sed用于单个行上的简单替换,即全部。对于其他任何你应该使用awk。使用GNU awk进行多字符RS和RT:

$ awk -v RS='"[^"]+"' -v ORS= '{gsub(/\n+/," ",RT); print $0 RT}' file
/biz/1-or-8;5.0;"a bunch of text with some linebreaks in between.";2016-11-03
/biz/1-or-8;2.0;"more text here.";2016-10-18