【问题标题】:Unix comand to convert Tab separated file to pipe separated fileUnix命令将制表符分隔文件转换为管道分隔文件
【发布时间】:2016-07-19 10:33:01
【问题描述】:

我的源 csv 文件是制表符分隔的,我想将其转换为管道 (|) 分隔文件。 这是一些示例记录。

Loan_Name   Current_Data_Status Mortgage_Loan_Seller

Market Basket   RECM-PS Transfer    Underwriters 

我在sed命令下面试过了。

sed -i 's/\t/|/g' Test.csv

它将制表符转换为|,但它在每一行的末尾添加了额外的|。下面是我得到的输出。

Loan_Name|Current_Data_Status|Mortgage_Loan_Seller| |
Market Basket|RECM-PS Transfer|Underwriters| | 

期望的输出应该是。

Loan_Name|Current_Data_Status|Mortgage_Loan_Seller
Market Basket|RECM-PS Transfer|Underwriters

请提供任何替代方法来实现这一点。

【问题讨论】:

  • 好像你最后有两个\t (tab)
  • 试试这个:sed 's/\t\+/|/g' file.csv
  • 我试过了,我得到了一个额外的 |在末尾。 Loan_Name|Current_Data_Status|Mortgage_Loan_Seller|市场篮子|RECM-PS 转让|承销商|
  • 已更新。现在试试这个:sed -e 's/\t\+$//g' -e 's/\t\+/|/g' file.csv
  • CSV = Comma-Separated Values。如果您的文件是制表符分隔的,那么它显然不是逗号分隔的,因此不要将其称为 CSV,因为这会产生误导。有些人会将其称为 TSV。非常重要的问题:你的最后一个字段可以是空的吗?例如foo<tab>bar<tab><tab> 可以出现在您的输入文件中吗?如果是这样,请将该示例添加到您的示例输入/输出中,因为它会破坏许多可能的答案。

标签: perl shell unix awk sed


【解决方案1】:

看起来你最后有两个标签。此外,仅供参考,tr 非常适合此类任务。

cat Test.csv | sed -E 's/\t+$//g' | tr '\t' '|' 

此命令首先删除所有尾随制表符。注意 -E 用于 Ubuntu 类型的 unix,在 bsd/MacOS 上可能是 -r。

【讨论】:

  • 似乎稍微容易一些(并非所有 sed 都将 \t 识别为选项卡):`
  • UUOC - sed 完全可以打开文件。
【解决方案2】:

一种简单的方法:删除所有尾随空格(包括制表符),然后运行简单的正则表达式。

有两个选项,具体取决于有空字段时所需的输出。

  1. 用管道替换每个选项卡。在这种情况下,如果有一个空字段,我们将有两个相邻的管道。这样我们就可以保留该字段,即使它是空的。

    perl -lne 's/\s*$//; s/\t/|/g; print' Test.csv
    
  2. 用一个竖线替换所有连续的标签。在这种情况下,如果有空字段,它们将完全消失。这样我们就完全删除了空字段。只会有单个管道。

    perl -lne 's/\s*$//; s/\t+/|/g; print' Test.csv
    

\t\t+ 之间的区别是——\t 匹配一个制表符,+ 表示任意数量的选项卡(至少一个)。

  • \t 精确匹配一个标签(并用管道替换它)。因此,如果有两个相邻的选项卡,每个选项卡都会被管道替换。
  • \t+ 匹配一个制表符、两个制表符或三个(连续的制表符)...并用一个管道替换所有制表符。

另一种方式:使用 Perl 的 split 来去掉尾随的东西

perl -lne 'print join "|", grep { not /^\s*$/ } split /(\t\s*)+/' Test.csv

split 丢弃任何尾随的空字段,因此我们先拆分。因为在这个数据的尾随字段中也可能有空格,我们需要\t\s*,因为这可能会导致额外的带有空格的字段,我们也会过滤。然后join 得到一个干净的列表,并根据要求使用管道。要覆盖原始文件,请添加-i

【讨论】:

  • @Zdim 我试过上面的命令,现在我没有得到额外的管道(|),但是空间也被管道(|)替换了我想用管道替换标签......: (
  • @Ashu Huh,对不起,我用空间来测试了! \s 应该是 \t。更新中。
  • 现在我没有得到额外的管道 (|) 最后它不起作用...:( Market Basket|RECM-PS Transfer|Underwriters|
  • @Ashu 我不明白……你是“没有得到额外的管道”——你的意思是,你得到了一个额外的管道?这意味着您在最后几个字段中还有一些额外的空格。更新了答案,请尝试。还添加了另一个版本。
  • @Ashu 太棒了!我建议你总是mark answers (link) 有用和/或解决你的问题。它可以帮助其他用户。如果还有其他事情请告诉我。
【解决方案3】:

您可以使用perl 实现相同的目的

perl -p -e 's/\t+/|/g' <Test.csv >Test.txt

如果要删除最后一个分隔符

perl -p -e 's/\t+/|/g' <Test.csv | sed -e 's/|$//' >Test.txt

【讨论】:

  • 我尝试了 perl 命令,但我仍然得到一个额外的 |在末尾。 Loan_Name|Current_Data_Status|Mortgage_Loan_Seller|市场篮子|RECM-PS 转让|承销商|
  • @Ashu,看起来你最后有两个制表符空格。使用perl -p -e 's/\t+/|/g;'s/\t\n//g' &lt;Test.csv &gt;Test.txt
  • @Ashu,更新了我的答案,也删除了最后一个分隔符。
  • 尝试使用更新的 perl 命令,但我仍然在每一行的末尾得到一个管道 (|)。市场篮子|RECM-PS 转让|承销商|
  • @Ashu,答案中有两个命令。你试过第二个吗?
【解决方案4】:

使用 GNU sed:

sed ':a;s/[\t ]*$//;Ta;s/\t/|/g' Test.csv

它会在将 \t 替换为 | 之前删除尾随的制表符/空格。

【讨论】:

    【解决方案5】:

    这可能对你有用(GNU sed):

    sed 's/\>\t\</|/g' file
    

    这会将单词之间的制表符转换为管道。但是它不会转换相邻的选项卡,即空字段。

    sed 's/\>\t\</|/g;s/\t//g' file
    

    将删除剩余的标签。

    sed 'y/\t/|/;s/\(\s*|\s*\)\+$/' file
    

    将制表符转换为管道并从行尾删除一个或多个管道(由可选空格分隔)。

    【讨论】:

      【解决方案6】:
      awk '{sub(/e   Current_Data_Status M/,"e|Current_Data_Status|M")}{sub(/t   RECM-PS Transfer    U/,"t|RECM-PS Transfer|U")}NF{print}' file
      
      Loan_Name|Current_Data_Status|Mortgage_Loan_Seller
      Market Basket|RECM-PS Transfer|Underwriters
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-24
        • 2015-04-21
        • 2020-07-21
        • 2016-12-17
        • 1970-01-01
        • 1970-01-01
        • 2014-10-15
        • 1970-01-01
        相关资源
        最近更新 更多