【问题标题】:Remove last part of string after dot from one column in a data file从数据文件的一列中删除点后字符串的最后一部分
【发布时间】:2014-10-31 10:21:35
【问题描述】:

也许这是一个简单的问题,但我检查了一些问题,但我无法为我的问题找到合适的解决方案。我有一个大文件,分为 10 列。在第 9 列中,有一个字符串,其中包含用点分隔的数字和字母。像这样的:

id.aa.xx.1.rr.2930
id.ee.yy.2.gres.1
id.ww.3232

我想要的是在最后一个点之后删除字符串的最后一部分。那么输出应该是这样的:

id.aa.xx.1.rr
id.ee.yy.2.gres
id.ww

如您所见,字符串没有相同的模式,因此我不能使用 split 函数,也不能在 python 中使用 rsplit() 因为点之后的最后一个字段每个字符串从 1 到 6 个字符。

在 python 或 awk 中有什么简单的解决方案?

【问题讨论】:

  • 请发完整行
  • rsplit() 有什么问题? s.rsplit('.', 1)[0] 应该可以正常工作。

标签: python design-patterns awk


【解决方案1】:

您可以使用此代码line[:line.rfind('.')]

【讨论】:

  • 不错的技巧,很容易添加到我的 python 代码中。很有用。谢谢
【解决方案2】:

在 python 中使用 re 模块可以解决问题

>>> x=['id.aa.xx.1.rr.2930', 'id.ee.yy.2.gres.1', 'id.ww.3232']
>>> for str in x:
...     re.sub(r"\.[^.]+$", "",str)
...
'id.aa.xx.1.rr'
'id.ee.yy.2.gres'
'id.ww'

或使用sed

$ sed -r 's/\.[^.]+$//g' input
id.aa.xx.1.rr
id.ee.yy.2.gres
id.ww

或者使用grep

$ grep -oP  "[\w.]+(?=\.[^.]+$)" input
id.aa.xx.1.rr
id.ee.yy.2.gres
id.ww

【讨论】:

    【解决方案3】:

    要编辑文件第 9 列中的值,您可以执行以下操作:

    awk '{n=split($9,a,".");$9="";for(i=1;i<n;++i)$9=$9 sprintf("%s%s",a[i],(i<n-1?".":""))}1' file
    

    使用 . 作为分隔符将第 9 列拆分为数组 a。通过遍历数组来重建值,跳过最后一个元素。末尾的 1{print $0} 的简写,用于打印该行。

    使用 GNU awk 更容易:

    gawk '{$9=gensub(/(.*)\..*$/, "\\1", 1, $9)}1' file
    

    正则表达式模式是贪婪的,因此直到最后一个 . 的所有内容都被捕获以用于替换。

    【讨论】:

    • gawkone two three four five six seven eight id.aa.xx.1.rr.2930 nine ten 提供了错误的结果。它给了one two three four five six seven eight one two three four five six seven eight id.aa.xx.1.rr nine ten。先awk就可以了
    • 你说得对,我只用一列对其进行了测试,所以对我来说效果很好。我错过了“如何”的论点,所以目标是$0。我现在编辑了。谢谢。
    【解决方案4】:

    如果所有行都需要删除它,则采用 awk 方式。

    awk 'sub(/\.[^\.]+$/,"",$9)' file
    

    如果其他行需要打印

    awk '{sub(/\.[^\.]+$/,"",$9)}1' file
    

    【讨论】:

    • 不错的一个。忘记了您可以指定要处理的字段。 PS 你应该使用awk '{sub(/\.[^\.]+$/,"",$9)}1' 来防止出现少于 9 行的问题而不会被打印。)
    • @jotne 我知道这就是为什么如果所有行都需要在我的答案开头删除它的原因:)
    • 如果没有括号,我仍然不会使用它。它甚至可以删除空行。与我的帖子相同,'NF--' 使用'{NF--}1' 效果更好
    • @Jotne 这不会中断,如果该行与sub 不匹配,它将愉快地继续,NF-- 的问题是该脚本会中断并导致错误。
    【解决方案5】:

    也许你可以使用 bash 来解决问题:

    echo id.aa.xx.1.rr.2930 | rev | cut -d. -f2- | rev
    

    结果:

    id.aa.xx.1.rr

    说明:

    rev: 反向行 --> 0392.rr.1.xx.aa.di

    剪切-d。 -f2- --> 删除反转字符串的第一个字段

    rev:再次将字符串反转为原始字符串

    【讨论】:

      【解决方案6】:

      这是一个简单的awk

      awk -F. -v OFS=. 'NF--' file
      id.aa.xx.1.rr
      id.ee.yy.2.gres
      id.ww
      

      它只是通过减少字段计数器NF来删除最后一个字段


      如果应该只在字段9 上完成,Tom 使用的拆分是一个很好的解决方案。

      【讨论】:

      • 我之前建议过这个,但删除了它,因为这仅适用于单个列,而 OP 正在寻找从文件的第 9 列中删除值。
      • @TomFenech 我明白了。然后 OP 应该发布了更正确的示例数据。我留下它,因为它对问题是正确的:Remove last part of string after dot 如果有人用谷歌搜索的话。
      • 我同意!这就是为什么我自己也犯了同样的错误:)
      • 很抱歉给您带来不便,我会在以后的场合中更加具体。但是感谢您的帮助。
      • 请注意,如果有空行,这将中断,因为 NF 不能为负数。最好使用NF&amp;&amp;NF-- 或仅使用{NF--}1
      【解决方案7】:

      使用 rev 和 cut:

      cat <filename> | rev | cut -d'.' -f'2-' | rev
      

      它的作用:

      • 反转行,以便我们不想要的部分位于开头
      • 使用 cut 以点 (.) 分割行并获取从第二个开始的所有字段
      • 将线反转回正常

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-03-28
        • 2012-09-01
        • 2013-08-05
        • 1970-01-01
        • 2015-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多