【问题标题】:awk equivalent of LTRIM function in Cawk 相当于 C 中的 LTRIM 函数
【发布时间】:2016-06-19 14:00:12
【问题描述】:

我只需要从字符串中删除前导 0。我发现在 C 中没有像 LTRIM 这样的内置函数。

我正在考虑使用以下 AWK 脚本来执行此操作:

awk -F"," 'BEGIN { a[$1] }
   for (v in a) {
       {if ($v == 0) {delete a[$v]; print a;} else exit;}
   }'

但我猜我没有正确声明数组,它会引发错误。抱歉,刚接触 AWK 编程。你能帮我把它放在一起吗?

【问题讨论】:

  • 标准 C 中没有函数 LTRIM()(也没有 ltrim())。如果您习惯使用上述功能,则它是您工作环境的非标准扩展。
  • 您要求我们帮助您做一些可能根本不需要做的事情。见xyproblem.info。发布示例输入和预期输出,以便我们了解您想要做什么,而不是您认为需要如何做,以便我们开始为您提供帮助。
  • @EdMorton 可能在错误的上下文中使用了“思考”这个词。我确实已经尝试了上述方法,但它引发了错误。将来在发布查询时会更加谨慎地放置正确的“输入”和“输出”。非常感谢您的指点
  • 不,thinking 这个词很好,只是有很多不同的方法可以修剪前导零,它们在不同的上下文中都有意义,所以除非你告诉我们为什么要修剪前导零我们只是扔掉一堆代码,任何/所有代码都可能对您的应用程序完全错误,即使它们都修剪前导零。

标签: arrays linux string bash awk


【解决方案1】:

您可以强制awk 将字段转换为数字,默认情况下前导零将被消除。

例如

$ echo 0001 | awk '{print $1+0}'

1

【讨论】:

    【解决方案2】:

    这是一个有点通用的ltrim 函数,可以称为ltrim(s)ltrim(s,c),其中c 是要修剪的字符(假设它不是特殊的正则表达式字符),其中c 默认为“” :

    function ltrim(s,c) {if (c==""){c=" "} sub("^" c "*","",s); return s}
    

    这可以用 0 来调用,例如ltrim($0,0)

    注意:

    这适用于一些特殊字符(例如“*”),但如果你想修剪特殊字符,直接调用适当的 sub() 函数可能是最简单的。

    【讨论】:

    • c 是一些正则表达式元字符时,您不能使用它,例如.。你需要sub("^[" c "]+",...
    • ...除非 c 是“^”...但我已经修改以澄清。感谢您的警惕。
    • 是的,我不确定它是否适用于“\”,但它会让你更接近。也许"^\" c "+"?身份证...
    【解决方案3】:

    如果我理解正确,并且您只是想从 bash 中的值中删除前导 '0's,您可以使用 sed 提供精确的正则表达式控制,或者一个简单的循环效果很好——并且消除了生成带有外部实用程序调用的子shell。例如:

    var=00104
    

    使用sed

    $ echo "$var" | sed 's/^0*//'
    104
    

    或使用 herestring 来消除 管道额外的子外壳(仅限 bash)

    $ sed 's/^0*//' <<<$var
    104
    

    使用带有字符串索引的简单循环

    while [ "${var:0:1}" = '0' ]; do
        var="${var:1}"
    done
    

    var 将在循环的 2 次迭代后包含 104

    【讨论】:

    • 这不处理值为零的特殊情况。
    • 它从来没有打算处理 trivial 的情况。只需对结果进行额外的测试。
    【解决方案4】:

    根据要求使用awk

    #!/usr/bin/awk -f
    /^0$/   { print; next; }
    /^0*[^0-9]/ { print; next; }
    /^0/    { sub("^0+", "", $0); print; next; }
            { print $0; }
    

    这提供了不将纯“0”修剪为空字符串,以及避免(可能)不必要地修剪非数字字段。如果后者实际上是所需的行为,则可以注释掉第二个模式/动作。无论哪种情况,替换都是可行的方法,因为将数字添加到非数字字段会产生错误。

    输入:

    0
    0x
    0000x
    00012
    

    输出:

    0
    0x
    0000x
    12
    

    输出修剪非数字字段:

    0
    x
    x
    12
    

    【讨论】:

    • 这可以更简洁地写成awk '/^0[0-9]+$/{sub(/^0+/,"")}1' file
    • 我允许像0123,456这样的输入
    • 啊,我明白了。与OP试图解决的问题一样好猜测!向非数字字段添加数字不会产生错误,顺便说一句,非数字字段将被视为数值为零的字符串。
    【解决方案5】:

    根据您最近发布的其他问题,您似乎正在努力学习awk 语言的基础知识。

    我不会尝试回答您最初的问题,而是尝试让您继续调查 语言。

    确实,awk 表达式的语法与 的语法相似。但是有一些重要的区别。

    我建议您花一些时间阅读 awk 入门并找一些练习。试试 Gnu Awk Getting Started

    也就是说,与C 有两个主要区别,我将在这里强调:

    1. 类型

    Awk 只使用字符串和数字——它根据上下文决定是否需要将输入视为文本或数字。在某些情况下 您可能需要强制转换为字符串或数字。

    1. 结构

    Awk 程序始终遵循一系列模式的相同结构,每个模式后跟一个动作,用花括号括起来:模式 { 动作 }:

    pattern { action }
    pattern { action }
    .
    .
    .
    pattern { action }
    

    模式可以是正则表达式或字符串或数字的比较。 如果模式评估为 true,则执行关联的操作。

    一个空的模式总是触发一个动作{ 操作 } 部分是可选的,等效于 { print }

    一个没有动作的空模式将什么都不做。

    BEGINEND 等一些模式得到特殊处理。在读取标准输入或打开任何文件之前,awk 将首先收集程序中的所有 BEGIN 语句并按顺序执行它们相关的操作

    然后它将开始处理标准输入或任何给定的文件,并将每一行置于所有其他模式/动作对按顺序

    一旦所有输入用尽,所有文件都将关闭,awk 将处理属于所有 END 模式的操作,再次按出现顺序。

    您可以使用BEGIN 操作来初始化变量。 END 操作通常用于报告摘要。

    警告:我们经常看到人们试图通过部分取消 awk 脚本或使用双引号来从 shell 传递数据。不要这样做;相反,使用 awk -v 选项将参数传递给程序:

    a="two"
    b="strings"
    awk -v a=$a \
        -v b=$b \
    'BEGIN {
        print a, b
    }'
    two strings
    

    【讨论】:

    • 非常感谢。你说对了我的问题。最近在我的工作中做了很多文件内容操作(和相当大的文件)。开始知道 awk 在这些场景中是最快的。再次感谢您让我开始使用 AWK。
    • 只是想解决您的需求 - 这是您问题的基本主题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-17
    • 2013-07-27
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 2021-01-09
    • 2020-08-21
    相关资源
    最近更新 更多