0

So I'm looking to write a script file which takes in a user-inputed number, and based off that number, it will execute a certain command. This command is the awk command that, of course, uses a field separator. I'm using awk on the following file /etc/passwd:

smiths|Login|2
olivert|Login|2
northj|Login|2
denniss|Login|2
smithd|Login|2
smiths|Time Reporting|210
olivert|Payroll|155
northj|Server Maintenance|70
northj|Logfile Reporting|45
denniss|Report Printing|80
smithd|Payroll Program Updates|150
smithd|Payroll Program Updates|180
smiths|Logout|2
olivert|Logout|2
northj|Logout|2
denniss|Logout|2
smithd|Logout|2

My issue is that I'm trying to use the pipe as the field separator, but when I try backslash-escaping the pipe (which is what I think I'm supposed to do), it's not actually quoting it. If I use something like a colon, it's fine:

case "$choice" in
    1)
       awk -F : '$2\n'
       ;;
    2)
       awk -F : '$1\n'
       ;;

Instead of the colon, I'm looking to use the pipe (refer to the file above) as the field separator. Any answers are appreciated!

1

Correct syntax is awk '-F[|]' '{ print $2 }'

The | is a shell special character, so it needs quoting to prevent shell trying to make a pipeline.

But | is also an awk special character, used to separate alternate patterns in a regular expression. Best way to quote that is to make it into a range consisting of a single character, as [|]. The -F option sets the awk variable FS (Field Separator), which is used as a regular expression (RE, pattern).

Then the whole thing needs quoting, because [..] can also be a shell special character, which expands filenames.

'$2\n' is a valid awk program, but it does not do what you expect. It is in the position of a pattern with no action. So if $2 is non-blank, the pattern is just True, and the whole line gets printed.

You want an action, which is what the { } does, and you want to select just one field and print it. It does not need a newline -- print does that automatically.

  • Isn't FS only used as a regular expression if it's longer than a single character? Using -F '|' or -F \| should work as expected. The issue is probably rather with the actual code. – Kusalananda Dec 3 at 10:55
  • The GNU/awk guide does say a single-char FS is not an RE (ignoring the one-space case), which is reasonable because it is hard to make an RE one character long. So you're right (again). But I have seen -F' *|' used to set FS to trim trailing blanks off all fields, and that really does no good. So I generally am very conservative in making a charset of anything that might be a special character in other circumstances. I also don't know just which awk the OP is using, and his current quoting does not work, and I just prefer to recommend a one-shot fix to problems. – Paul_Pedant 2 days ago
  • GNU awk follows the POSIX spec in this regard. A space is special, but any other single character should be taken as exactly that character, and not as a regular expression. – Kusalananda 2 days ago
  • I didn't spot the OPs Linux tag, but he still might be in mawk. I'm aware that SunOS and AIX awk can be non-conforming (plenty pain in the past, including not permitting a space between -F and the character). I said you're right about the single char, but mine works too and is less likely to be broken by maintenance. For the record, I prefer BEGIN { FS = ... } for any significant script, because I like the FS not to be detached into the command line, which may be some distance away. – Paul_Pedant 2 days ago

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.