【问题标题】:How to replace a text sequence that includes "\n" in a text file如何替换文本文件中包含“\n”的文本序列
【发布时间】:2015-12-19 22:29:20
【问题描述】:

这听起来可能是重复的,但我无法做到这一点。

考虑:

_ = 空格
- = 减号

particle_little.csv 是这种形式的文件:

waste line to be deleted
__data__data__data
_-data__data_-data
__data_-data__data

我需要particle_std.csv 中的标准 csv 格式,如下所示:

data,data,data
-data,data,-data
data,-data,data

我正在尝试使用tailtr 进行转换,这里我拆分命令:

  1. tail -n +2 particle_little.csv删除第一行
  2. | tr -s ' ' 删除重复的空格
  3. | tr '/\b\n \b/' '\n' 删除最开始的空格
  4. | tr ' ' ',' 更改逗号的空格
  5. > particle_std.csv 将其放入输出文件中

但我明白了(没有第四步):

data
data
data
-data
...

最后,文件很大,用编辑器打开几乎是不可能的(我知道有超级编辑器可能可以)

【问题讨论】:

  • 在我看来,您尝试使用错误的工具来完成这项工作;有趣的是,它的效果不是很好。您是否仅限于使用trtail?还是您只需要完成工作,而这些是第一批出现的工具? “数据”部分是否包含空格?大概不会。
  • 我需要得到输出,是的,这些是我发现的第一个工具(所以,我是新手)
  • 顺便说一下,文件很大
  • 巨大的文件不是问题,只要你不试图一次把它全部吸入内存,只要你不试图把它写到太多的管道上。零管最好;一根管子不是大问题;二十根管道可能是个问题(它仍然可能是正确的,但通常不是')。

标签: regex bash csv tr


【解决方案1】:

我建议你使用 awk:

$ cat file
waste line to be deleted
  data  data  data
 -data  data -data
  data -data  data
$ awk -v OFS=, '{ $1 = $1 } NR > 1' file
data,data,data
-data,data,-data
data,-data,data

脚本将输出字段分隔符OFS 设置为, 并将第一个字段重新分配给它自己$1 = $1,导致awk 接触每一行(并用逗号替换空格)。第一行之后的行,NR > 1,被打印(默认操作是打印该行)。

【讨论】:

  • 哦!伙计,这很神奇,同时让我的解决方案很有趣......谢谢,你能解释一下你使用的选项吗?
  • 我已经更新了我的答案来解释一下,还有什么不清楚的地方吗?
【解决方案2】:

所以,如果我没看错的话 - 请忽略 以空格开头的行。逗号分隔其他所有内容。

我建议perl:

perl -lane 'next unless /^\s/; print join ",", @F'; 

这个,当给出时:

waste line to be deleted
  data  data  data
 -data  data -data
  data -data  data

STDIN(或在文件名中指定)输出:

data,data,data
-data,data,-data
data,-data,data

这是因为:

-l 去除换行符(并在每个print 之后替换它们);

-a 在任何空白处自动拆分

-n 将其包装在 while ( <> ) { 循环中,该循环逐行迭代 - 从功能上讲,这意味着它就像 sed/grep/tr 一样工作,并读取 STDIN 或指定为 args 的文件。

-e 允许指定 perl sn-p。

在这种情况下:

  • 跳过所有不以\s 或任何空格开头的行。
  • 任何其他行,以, 作为分隔符加入字段(由-a 生成的@F)。 (这会自动插入换行符,因为-l

然后您可以将输出重定向到文件 (>output.csv) 或使用 -i.bak 就地编辑。

【讨论】:

    【解决方案3】:

    您可能应该为此使用sedawk

    sed -e 1d -e 's/^  *//' -e 's/  */,/g'
    

    在 Awk 中的一种方法是:

    awk 'NR == 1 { next }
         { pad=""; for (i = 1; i <= NF; i++) { printf "%s%s", pad, $i; pad="," } print "" }'
    

    但在 Awk 中有更好的方法:

    awk 'BEGIN { OFS=","} NR == 1 { next } { $1 = $1; print }' data
    

    BEGIN 块设置输出字段分隔符;分配$1 = $1; 强制Awk 重新处理输出行; print 打印出来。

    我保留了第一个 Awk 版本,因为它表明有不止一种方法可以做到这一点,而且在某些情况下,这些方法可能很有用。但是对于这个任务,第二个 Awk 版本更好——更简单、更紧凑(并且与 Tom Fenechanswer 同构)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-08
      • 1970-01-01
      • 2019-07-14
      • 1970-01-01
      • 2014-02-07
      • 2011-09-18
      • 2013-11-30
      • 2021-01-20
      相关资源
      最近更新 更多