【问题标题】:Need help trimming CSV file with awk and sed without hacking it需要帮助使用 awk 和 sed 修剪 CSV 文件而不破解它
【发布时间】:2013-01-18 16:37:53
【问题描述】:

我搜索了堆栈,但遇到了一个特定的 CSV 文件:

我有一个分为两列的大型 CSV 文件:

Name    Extension
Brian Aducci    6598
Jeff Alexander  6661
Sara Alfieri    6789

我想保留扩展名并将名称修剪为用户名:

Name    Extension
BAducci 6598
JAlexander 6661
SAlfieri 6789

【问题讨论】:

  • 有什么方法可以将Brian Aducci 转换为BAducci?是名字的第一个字符和姓氏吗?

标签: bash csv awk sed


【解决方案1】:

这条短线应该可以满足您的需求:

awk 'NR>1{$0=substr($1,0,1)$2" "$3}1' file

测试

kent$  echo "Name    Extension
Brian Aducci    6598
Jeff Alexander  6661
Sara Alfieri    6789"|awk 'NR>1{$0=substr($1,0,1)$2" "$3}1'
Name    Extension
BAducci 6598
JAlexander 6661
SAlfieri 6789

【讨论】:

    【解决方案2】:

    试试这个

    awk '{if( NR==1 ){print $1" "$2; next}}{a=substr($1,1,1); print a$2" "$3}' temp.txt

    【讨论】:

    • 名字可以有一个或多个名字...我试图涵盖这一点(但在某些国家可能更复杂...)。并且标题也可能会有所不同...我只是将其打印出来
    • Olivier,你能举个例子吗?
    • @OlivierDulacc 我是新手,目前我只能根据用户输入和他的预期输出提供解决方案。我可以做出很多假设,这样我就永远无法回答一个问题。但是 OP 有权尝试每种解决方案并选择适合他的解决方案。我也会尝试向你们学习更多
    • @user19340357 当然,但我只是指出不要假设名称部分只有 2 列。例如:约翰·刘易斯·史密斯。但是,对于“firstname=$1 lastname=$2”的情况,您的示例很好。我们都在不断学习:)(我在这些网站上阅读热门答案学到了很多)
    • 我的回答确实有效。既适用于海报显示的名称:“firstname lastname”,也适用于“firsname1 firsname2 ... lastname”的(可能存在,并没有什么坏处)的情况
    【解决方案3】:

    任何将Brian Aducci 转换为BAducci 的方法?

    是名字的第一个字符和姓氏吗?如果是,那么下面应该可以工作:

    {read x; echo $x; while read x y; do echo ${x:0:1}$y; done; } <large_file >output_file
    

    sed 方法:

    sed -r '1!s/^(.)[^ ]* */\1/' large_file >output_file
    

    【讨论】:

      【解决方案4】:

      awk 是我的选择

      awk 'NF>2{ for (i=1;i<NF -1;i++){ initials=initials substr($i,0,1) }; print initials $(NF-1), $NF}' x.txt
      

      检查字段数(NF)是否大于2 然后遍历字段 1 - NF-1 然后取每个的第一个字母并将其放入 initials 变量中。 然后我们打印出姓名首字母和扩展名。

      【讨论】:

        【解决方案5】:

        让我们假设它不是 2,而是“至少 3”列... firsname lastname extension

        也许有不止 1 个名字(这种情况经常发生)

        让我们假设:登录是第一列的第一个字符,+ 第 n-1 列(=名称)

        你会这样做:

        gawk '(NR == 1) { print ; next ;} /./ { name=NF-1 ; print substr($1,1,1) $name " " $NF }' /the/file
        

        如果你有这将工作

        Name    Extension
        firstname1                lastname1   extension1
        firstname2a  firsntname2b lastname2   extension2
        ...
        

        (即无论名字有多少,1 个或多个)(无论每个字段有多少空格或制表符)

        (NR == 1) { print ; next ; } 部分是“按原样”打印第一(标题)行,然后“下一个”到其他行。没有表头的可以把这个去掉。

        在其他行上,NR>1,因此只有第二个模式(/./,意思是“如果行不为空”)适用,它会打印您需要的内容(如果有奇怪的名称,请更改它: john john name1 name2,但应该很少见)

        您还可以使用 gnu awk(或 nawk)'tolower' 强制将某些内容变为小写:

        gawk '(NR == 1) { print ; next ;} /./ { name=NF-1 ; print tolower(substr($1,1,1)) tolower($name) " " $NF }' /the/file
        

        【讨论】:

        • 这当然适用于 2 列名称。但如果一个人有多个名字(假设它写成:“firstname1 fierstname2 ... lastname extension”)也可以使用
        • @sudo_O 我对你的投了反对票,因为它不工作,不是因为紧凑......一旦它再次工作,我就收回了我的反对票,所以我不再反对它。那么......为什么你在这里投反对票,究竟是什么?......这是某种仇杀吗?
        • 它确实有效。只需更改“/the/file”以指向包含数据的文件。或者取出“/the/file”,然后使用管道中的剩余行。
        • ???它不是。 questino 没有显示任何逗号,我复制/粘贴了他显示的 4 行,我的程序完全显示了他希望看到的内容。别再说错误信息了。我再说一遍:一旦你的投票被纠正,我就取消了我的反对票。不要再幼稚和说错误信息了......
        • 这太完美了,如果可以的话,我会赞成。再次感谢!
        【解决方案6】:

        这与 Sudo_O 的sed 解决方案基本相同。将sed 用于此类事情的问题在于sed 的许多版本根本不支持所使用的功能。 (例如,-r 是一个非标准选项,用于使+ 成为正则表达式中的魔术字符。许多sed 根本不提供对+ 的支持)

        perl -pe 's/^(.)/\S*\s/$1/ if $. > 1' input-file
        

        【讨论】:

        • Many sed simply do not provide support for + sed 的哪些实现不支持扩展正则表达式?虽然-r 是GNU 选项,但它也支持-E,这是此* 的BSD 选项(反之则不然)。
        • -e-f-n 是唯一的标准选项。其他任何东西都不能可靠地使用。
        【解决方案7】:

        使用sed 实际上更容易:

        $ cat file
        Name   Extension
        Brian  Aducci     6598
        Jeff   Alexander  6661
        Sara   Alfieri    6789
        
        $ sed -r '2,$s/(.)\w+\s+/\1/' file
        Name        Extension
        BAducci     6598
        JAlexander  6661
        SAlfieri    6789
        

        awk 的一种方式:

        $ awk 'NR>1{sub(/\w+\s+/,substr($0,1,1),$0)}1' file
        Name        Extension
        BAducci     6598
        JAlexander  6661
        SAlfieri    6789
        

        【讨论】:

        • @我试过 sed 解决方案不起作用。我有空格分隔文件
        • @user19340357 sed 解决方案在两者上都经过测试,并且可以在 GNU sed 上运行,也就是说,您在 OSX 上吗?
        • ^sudo_O :我现在很困惑:为什么您要为不是提问者所拥有的测试文件显示“解决方案”? ...他没有“,”,而是用空格分隔字段
        • 我在 Linux 上,它不打印第一个单词的 firstLtter,而只打印第二个单词。像这样sed -nr '1p;2,${s/(.)\w+\s+/\1/p}' temp.txt Name Extension Aducci 6598 Alexander 6661 Alfieri 6789
        • @OlivierDulac 因为我阅读了这个问题,并且 OP 说他有一个 CSV 文件(逗号分隔值),现在才清楚哪个.. 两种解决方案都适用于两者,为什么 -1?
        猜你喜欢
        • 1970-01-01
        • 2018-04-04
        • 2015-01-12
        • 2014-05-23
        • 2022-10-24
        • 1970-01-01
        • 1970-01-01
        • 2012-08-30
        • 2020-04-13
        相关资源
        最近更新 更多