1

Let's say I have a file.csv as the following:

id;filename;device
1;118574934-20220503-17h44m20s101;
2;118574934-20220503-17h44m20s101;
3;118574934-20220503-17h44m20s101;DEVICE-0001-33
4;118574934-20220503-17h44m20s101;DEVICE-0001-33
5;118574934-20220503-17h44m20s101;DEVICE-0001-33
6;118574934-20220503-17h44m20s101;DEVICE-0001-33
7;118574934-20220503-17h44m20s101;DEVICE-0001-33

I've created an awk script for handling getting the device name when it appears on my file and then it finishes its execution. The script.awk is functional and is as the following:

BEGIN {
    FS=";"
}
NR > 1 { fileName = $2 }
NR > 1 { if ( $3 != "" ) { device = $3; exit} }
END {
    if ( device == "" ) {
        line = "UNCONNECTED_"fileName".txt;UNCONNECTED"
    } else {
        line = device"_"fileName".txt;"device
    }
    print "filename;folder"
    print line
}

Its output after executing awk -f script.awk file.csv is:

filename;folder
DEVICE-0001-33_118574934-20220503-17h44m20s101.txt;DEVICE-0001-33

The problem is that I'd like to split the string DEVICE-0001-33 into DEVICE-0001. Since I've already used FS with ; and I can't use FS again as - in order to split my device variable. How can I handle that using only awk? How can I split a variable with a specific character once FS is already being used?

0

1 Answer 1

6

For your case, using sub() seems enough. Instead of assigning $3, which is DEVICE-0001-33, to your variable, you want to use a substring of it. Assuming that - is the separator inside there, you want to remove the last field.

echo "DEVICE-0001-33" | awk '{sub(/-[^-]*$/,"",$1); print}'

DEVICE-0001

We use -[^-]*$ in order to get the last separator together with the last field. And not just -.*$ because it's greedy and will eat all the fields but the first. The replacement is the empty string "". And the result is written to the field. So you can replace device = $3 with

sub(/-[^-]*$/,"",$3); device = $3

The general answer to the title of your question is to use the split() function. It gives you the ability to treat a field or any string, like if it was a record, a line with fields, using a separator different than the FS. This example describes what it is doing:

echo "DEVICE-0001-33" | awk -v s='-' '{
    n=split($1,arr,s)
    print "number of fields: " n
    print "separator: " s
    for (i=1;i<=n;i++) print "field: " i " value: " arr[i]
}'

number of fields: 3
separator: -
field: 1 value: DEVICE
field: 2 value: 0001
field: 3 value: 33

And you can do on this string what awk can do for a line.

2
  • Thanks, using the regular expression looks more straightforward for sure. I think that in my specific case I'd have to create that for loop in order to join the string if I used the split function...
    – raylight
    May 4 at 0:03
  • 1
    Yes, for operations like "remove the last field", "get only the first one" etc, sub() and gsub() are very handy. You would have to use split(), if you 'd like to re-order the sub-fields, or print them reversed, or get their number etc.
    – thanasisp
    May 4 at 0:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.