awk equivalent of LTRIM function in C

2019-08-14 16:21发布

I need to delete leading 0s only from a string. I found that there is no in-built function like LTRIM as in C.

I'm thinking of the below AWK script to do that:

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

But guess I'm not declaring the array correctly, and it throws error. Sorry new to AWK programming. Can you please help me to put it together.

5条回答
smile是对你的礼貌
2楼-- · 2019-08-14 16:58

Using awk, as requested:

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

This provides for not trimming a plain "0" to an empty string, as well as avoiding the (probably) unwanted trimming of non-numeric fields. If the latter is actually desired behavior, the second pattern/action can be commented out. In either case, substitution is the way to go, since adding a number to a non-numeric field will generate an error.

Input:

0
0x
0000x
00012

Output:

0
0x
0000x
12

Output trimming non-numeric fields:

0
x
x
12
查看更多
Melony?
3楼-- · 2019-08-14 17:05

Based on other recent questions you posted, you appear to be struggling with the basics of the awk language.

I will not attempt to answer your original question, but instead try to get you on the way in your investigation of the language.

It is true that the syntax of awk expressions is similar to . However there are some important differences.

I would recommend that you spend some time reading a primer on awk and find some exercises. Try for instance the Gnu Awk Getting Started.

That said, there are two major differences with C that I will highlight here:

  1. Types

Awk only uses strings and numbers -- it decides based on context whether it needs to treat input as text or as a number. In some cases you may need to force conversion to string or to a number.

  1. Structure

An Awk program always follows the same structure of a series of patterns, each followed by an action, enclosed in curly braces: pattern { action }:

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

Patterns can be regular expressions or comparisons of strings or numbers. If a pattern evaluates as true, the associated action is executed.

An empty pattern always triggers an action. The { action } part is optional and is equivalent to { print }.

An empty pattern with no action will do nothing.

Some patterns like BEGIN and END get special treatment. Before reading stdin or opening any files, awk will first collect all BEGIN statements in the program and execute their associated actions in order.

It will then start processing stdin or any files given and subject each line to all other pattern/action pairs in order.

Once all input is exhausted, all files are closed, and awk will process the actions belonging to all END patterns, again in order of appearance.

You can use BEGIN action to initialize variables. END actions are typically used to report summaries.

A warning: Quite often we see people trying to pass data from the shell by partially unquoting the awk script, or by using double quotes. Don't do this; instead, use the awk -v option to pass on parameters into the program:

a="two"
b="strings"
awk -v a=$a \
    -v b=$b \
'BEGIN {
    print a, b
}'
two strings
查看更多
疯言疯语
4楼-- · 2019-08-14 17:07

If I understand correctly, and you just want to trim the leading '0's from a value in bash, you can use sed to provide precise regex control, or a simple loop works well -- and eliminates spawning a subshell with the external utility call. For example:

var=00104

Using sed:

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

or using a herestring to eliminate the pipe and additional subshell (bash only)

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

Using a simple loop with string indexes:

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

var will contain 104 following 2 iterations of the loop.

查看更多
We Are One
5楼-- · 2019-08-14 17:14

Here is a somewhat generic ltrim function that can be called as ltrim(s) or ltrim(s,c), where c is the character to be trimmed (assuming it is not a special regex character) and where c defaults to " ":

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

This can be called with 0, e.g. ltrim($0,0)

NOTE:

This will work for some special characters (e.g. "*"), but if you want to trim special characters, it would probably be simplest to call the appropriate sub() function directly.

查看更多
祖国的老花朵
6楼-- · 2019-08-14 17:22

you can force awk to convert the field to a number and leading zeros by default will be eliminated.

e.g.

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

1
查看更多
登录 后发表回答