0

In the following awk code part, file contains a file name with its full Linux path that may include a directory of the type backup-YYMMDD where YYMMDD is a date.

I would like to assign YYMMDD to isDate[file], that is isDate[file]=YYMMDD.

How can I do that?

for (file in files) {
        if ( file ~ /(^|\/)(library|labs data|current)(\/|$)/ ) {
           isKeep[file]
        }
        else if ( file ~ /(^|\/)(backup-[0-2][0-9][0-1][0-9][0-3][0-9])(\/|$)/ ) {
            isDate[file]
        }
        else {
            isDelete[file]
        }
}
New contributor
macxpat is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
1

GNU awk has the match command which allows you to extract the actual value of string components characterized by a pattern. Thus, you could use

match(file,"^[[:print:]]*(backup-[0-2][0-9][0-1][0-9][0-3][0-9])[[:print:]]*$",pats);
isDate[file]=pats[1]

in the else if .... part of your program. The (array) variable pats will then be filled with all (...)-enclosed sub-expressions in your RegExp which are found in the string, starting with index 1 (pats[0] would be the actual value of the entire expression). Since we only have one sub-expression thus grouped (the backup-YYMMDD part), pats[1] contains what you are looking for.

Alternatively, you could try directly

...
   else if (match(file,"^[[:print:]]*(backup-[0-2][0-9][0-1][0-9][0-3][0-9])[[:print:]]*$",pats)==1) {
      isDate[file]=pats[1]
   }
...

Note that this approach, of course, relies on the being only one path component containing the backup-YYMMDD pattern.

Edit (on a note by the OP, @macxpat)

I used string constants ("^[[:print:]] ... $") for specifying the regular expression in this answer. However, as noted in the GNU Awk User's Guide, it is cleaner and more efficient to specify them as regular expression constants. Thus, better use

match(file,/^[[:print:]]*(backup-[0-2][0-9][0-1][0-9][0-3][0-9])[[:print:]]*$/,pats)

in the above examples!

  • Thank you! This exactly answers my question. I appreciate also your clear description: "a command which allows you to extract the actual value of string components characterized by a pattern". I have modified the title of my question in accordance, so it may be more useful to others. I was not able to make a successful search because I couldn't even formulate in plain words what I wanted to do! – macxpat Dec 3 at 1:29
  • 1
    You're welcome! Concerning question (1): As you probably know, [ ... ] defines a "character list", i.e. a list of characters accepted at this position of the RegExp. The [:print:] is a "character class" and interpreted as "any printable character" (as opposed to control characters). Thus, [[:print:]] is a character list containing (only) all printable characters. There are similar constructs for digits, alphanumeric etc., but note that these are all POSIX extensions. As for question (2): it's actually a bad habit probably taken over from C printf; using RegExp constants is cleaner. – AdminBee Dec 3 at 7:37
  • 1
    As for character classes, the [[:digit:]] is particularly useful as replacement for [0-9] because the interpretation of that kind of specification depends on the locale-specific character sort order and may not always mean 0123456789! – AdminBee Dec 3 at 10:15
  • 1
    The reason for the behaviour is that I anchored the RegExp at the beginning of the line using the ^ symbol, so if the regular expression matches at all, it must by definition match at position 1 in the string. Notice that match returns the position where the entire RegExp occurs, not only the ( ... )-grouped sub-expression. In the check whether a line matches at all, I could as well have said if (match( ... )!=0) to exclude non-matching lines; forcing it to be equal 1 can serve as a (not really necessary) consistency check ... – AdminBee yesterday
  • 1
    Btw, please notice that "the comment section is not for extended discussions". If you have further need for clarification, opening up a Unix & Linux Chat may be the better means (although I personally think your questions are of interest to a wider audience). – AdminBee yesterday

Your Answer

macxpat is a new contributor. Be nice, and check out our Code of Conduct.

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.