【问题标题】:How to remove a specific string common in multiple lines in a CSV file using shell script?如何使用 shell 脚本删除 CSV 文件中多行中常见的特定字符串?
【发布时间】:2015-06-21 02:30:11
【问题描述】:

我有一个 csv 文件,其中包含 65000 行(大小约为 28 MB)。在每一行中,都给出了开头的特定路径,例如“c:\abc\bcd\def\123\456”。现在假设路径“c:\abc\bcd\”在所有行中都是通用的,其余内容不同。我必须使用 shell 脚本从所有行中删除公共部分(在本例中为“c:\abc\bcd\”)。例如CSV文件的内容如前所述。

C:/Abc/Def/Test/temp\.\test\GLNext\FILE0.frag                   0   0   0
C:/Abc/Def/Test/temp\.\test\GLNext\FILE0.vert                   0   0   0
C:/Abc/Def/Test/temp\.\test\GLNext\FILE0.link-link-0.frag       16  24  3
C:/Abc/Def/Test/temp\.\test\GLNext\FILE0.link-link-0.vert       87  116 69
C:/Abc/Def/Test/temp\.\test\GLNext\FILE0.link-link-0.vert.bin   75  95  61
C:/Abc/Def/Test/temp\.\test\GLNext\FILE0.link-link-0            0   0
C:/Abc/Def/Test/temp\.\test\GLNext\FILE0.link-link-6            0   0   0 

在上面的例子中,我需要如下输出

FILE0.frag                  0   0   0
FILE0.vert                  0   0   0
FILE0.link-link-0.frag      17  25  2
FILE0.link-link-0.vert      85  111 68
FILE0.link-link-0.vert.bin  77  97  60
FILE0.link-link-0               0   0
FILE0.link                  0   0   0

你们中的任何人都可以帮我解决这个问题吗?

【问题讨论】:

  • 您能否编辑问题以包含几行示例输入和预期输出?公共子串是提前知道的还是应该从输入中计算出来的?
  • 如果不按照@Wintermute 的建议进行操作,您最终会得到一个答案,该答案可能会为某些特定输入集产生您想要的输出,但这是一种绝对荒谬的获取方式,并且可能行不通所有可能的输入。

标签: linux shell csv awk sed


【解决方案1】:

你可以使用sed:

$ cat test.csv 
"c:\abc\bcd\def\123\456", 1, 2
"c:\abc\bcd\def\234\456", 1, 2
"c:\abc\bcd\def\432\456", 3, 4

$ sed -i.bak -e 's/c\:\\abc\\bcd\\//1' test.csv

$ cat test.csv
"def\123\456", 1, 2
"def\234\456", 1, 2
"def\432\456", 3, 4

我这里是这样使用sed的:

sed -e 's/<SEARCH TERM>/<REPLACE_TERM>/<OCCURANCE>' FILE

在哪里

  • &lt;SEARCH TERM&gt; 是我们要查找的内容(在本例中为 c:\abc\bcd\,但需要转义反斜杠)。
  • &lt;REPLACE TERM&gt; 是我们想要替换的,在这种情况下什么都没有,并且
  • &lt;OCCURANCE&gt; 是我们要替换的项目的出现位置,在这种情况下是每行中的第一项。

-i.bak代表:不输出,只编辑这个文件。(但要先备份))

根据@david-c-rankin 评论更新。他是对的,在编辑文件之前做好备份,以防万一出错。

【讨论】:

  • sed -i.bak ... filename 代表 edit filename in place,但如果我搞砸了,请在 filename.bak 中为我备份。最好以后再删除 .bak 文件...
【解决方案2】:
# init variable
MaxPath="$( sed -n 's/,.*//p;1q' YourFile )"
GrepPath="^$( printf "%s" "${MaxPath}" | sed 's#\\#\\\\#g' )"

# search the biggest pattern to remove
while [ ${#MaxPath} -gt 0 ] && [ $( grep -c -v -E "${GrepPath}" YourFile ) -gt 0 ]
 do
   MaxPath="${MaxPath%%?}"
   GrepPath="^$( printf "%s" "${MaxPath}" | sed 's#\\#\\\\#g' )"
 done

# Adapt your file
if [ ${#MaxPath} -gt 0 ]
 then
   sed "s#${GrepPath}##" YourFile
 fi
  • 假设 MaxPath 中没有特殊的正则表达式字符和 # 示例
  • grep -c -v -E 没有在性能方面进行优化(每次处理 whle 文件,因为它可以在第一次未命中时停止)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 2018-12-22
    • 1970-01-01
    • 2023-01-09
    • 2012-11-14
    • 2019-12-13
    • 2012-12-21
    相关资源
    最近更新 更多