【问题标题】:Unix cut: Print same Field twiceUnix cut:两次打印相同的字段
【发布时间】:2012-09-06 11:21:55
【问题描述】:

假设我有文件 - a.csv

ram,33,professional,doc
shaym,23,salaried,eng

现在我需要这个输出(请不要问我为什么)

ram,doc,doc,
shayam,eng,eng,

我正在使用剪切命令

cut -d',' -f1,4,4 a.csv

但输出仍然存在

ram,doc
shyam,eng

这意味着 cut 只能打印一次一个字段。我需要将同一字段打印两次或 n 次。 我为什么需要这个?(可选阅读) 啊。说来话长。我有一个这样的文件

#,#,-,-
#,#,#,#,#,#,#,-
#,#,#,-

我必须将其转换为

#,#,-,-,-,-,-
#,#,#,#,#,#,#,-
#,#,#,-,-,-,-

这里每个“#”和“-”指的是不同的数字数据。谢谢。

【问题讨论】:

  • 这是作业吗?为什么只能使用cutsed
  • 输出行必须以逗号结尾吗?
  • 你的意思是每一行都应该有相同数量的字段?

标签: shell unix sed cut


【解决方案1】:
$ sed 's/,.*,/,/; s/\(,.*\)/\1\1,/' a.csv
ram,doc,doc,
shaym,eng,eng,

这是做什么的:

  • 用逗号替换第一个和最后一个逗号之间的所有内容
  • 重复最后一个“,something”部分并添加逗号。瞧!

假设:

  • 您需要第一个字段,然后是最后一个字段的两倍
  • 第一个和最后一个字段中没有转义逗号

为什么你需要这个输出? :-)

【讨论】:

  • 我是否在我的问题中附上了问题的范围。
【解决方案2】:

您不能将同一字段打印两次。 cut 按顺序打印选择的字段(或字符或字节)。有关一些非常相似的请求,请参阅 Combining 2 different cut outputs in a single command?Reorder fields/characters with cut command

这里使用的正确工具是 awk,如果您的 CSV 在字段周围没有引号。

awk -F , -v OFS=, '{print $1, $4, $4}'

如果您不想使用 awk(为什么?什么奇怪的系统有 cutsed 但没有 awk?),您可以使用 sed(仍然假设您的 CSV 没有引号字段)。匹配前四个逗号分隔的字段,然后按您想要的顺序选择您想要的。

sed -e 's/^\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\)/\1,\4,\4/'

【讨论】:

  • 这是awk/中更好的解决方案,Jens提供的sed解决方案
  • 关于 awk 和 range 打印的一件事是与 cut 相比它的速度较慢。每行调用两次 cut 会很好。
  • @JohnJiang 没错,awk 通常比 sed 慢,而 sed 比 cut 等专用工具慢。您只会注意到非常大的文件(数百万条记录)。在我链接的一个线程中有一个剪切+粘贴解决方案,对于非常大的文件可能更快。
【解决方案3】:

正如其他人所指出的,cut 不支持字段重复。

你可以结合cutsed,例如如果重复元素在末尾:

< a.csv cut -d, -f1,4 | sed 's/,[^,]*$/&&,/'

输出:

ram,doc,doc,
shaym,eng,eng,

编辑

要使重复变量,您可以执行以下操作(假设您有 coreutils 可用):

n=10
rep=$(seq $n | sed 's:.*:\&:' | tr -d '\n')
< a.csv cut -d, -f1,4 | sed 's/,[^,]*$/'"$rep"',/'

输出:

ram,doc,doc,doc,doc,doc,doc,doc,doc,doc,doc,
shaym,eng,eng,eng,eng,eng,eng,eng,eng,eng,eng,

【讨论】:

    【解决方案4】:

    使用 perl:

    perl -F, -ane 'chomp($F[3]);$a=$F[0].",".$F[3].",".$F[3];print $a."\n"' your_file
    

    使用 sed:

    sed 's/\([^,]*\),.*,\(.*\)/\1,\2,\2/g' your_file
    

    【讨论】:

      【解决方案5】:

      我遇到了同样的问题,但我没有将所有列添加到 awk,而是使用(复制第二列):

      awk -v OFS='\t' '$2=$2"\t"$2' # for tab-delimited files

      对于 CSV,您可以使用

      awk -F , -v OFS=, '$2=$2","$2'

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-12
        • 2016-12-23
        • 1970-01-01
        • 2011-03-17
        • 2018-12-28
        相关资源
        最近更新 更多