2

I have a file with some lines like these:

ENVIRONMENT="myenv"
ENV_DOMAIN='mydomain.net'
LOGIN_KEY=mykey.pem

I want to extract the parts after the = but without the surrounding quotes. I tried with gsub like this:

awk -F= '!/^(#|$)/ && /^ENVIRONMENT=/ {gsub(/"|'/, "", $2); print $2}' 

Which ends up with -bash: syntax error near unexpected token ')' error. It works just fine for single matching: /"/ or /'/ but doesn't work when I try match either one. What am I doing wrong?

Unihedron
  • 10,902
  • 13
  • 62
  • 72
MacUsers
  • 2,091
  • 3
  • 35
  • 56
  • It should be escaped like `\)` and Is single quote allowed within single quotes? – Braj Aug 14 '14 at 13:51
  • It is just a typo in `gsub()` function: you use `'` to close the quoting instead of `"`. Just replace `/"|'/` with `/"|"/`. – fedorqui Aug 14 '14 at 13:57
  • 3
    Three comments: (1) what about _ill formed_ definition: `ENVIRONMENT='old env"` (2) what about embedded quotes: `ENVIRONMENT="good ol'env"` (3) The two parts of your selector are redundant: `/^(#|$)/` cannot be true if `/^ENVIRONMENT=/` is true. – Sylvain Leroux Aug 14 '14 at 14:00
  • possible duplicate of [Escaping single-quotes within single-quoted strings](http://stackoverflow.com/questions/1250079/escaping-single-quotes-within-single-quoted-strings) – Aserre Aug 14 '14 at 14:03
  • @SylvainLeroux Once rewritten to work (something like this : `awk -F= '!/^(#|$)/ {gsub(/"|'"'"'/, "", $2); print $2}' myfile`), it will remove the quotes in your case 1) or 2). – Aserre Aug 14 '14 at 14:18
  • 2
    awk fundamental 1: you cannot use a `'` inside a `'`-delimitted script. You need to use `\047` or some other method instead of the literal `'`' character. awk fundamental 2: you cannot have 2 separate "start-of-line-regexp" conditions that are both true. Get the book "Effective Awk Programming, Third Edition" by Arnold Robbins. – Ed Morton Aug 14 '14 at 14:19
  • @Ploutox But is the middle `'` removal desired is case (2) ? For `ENVIRONMENT` this is kind of stupid, but might be relevant, say, for `PASSWORD="my good ol'passwd"`. – Sylvain Leroux Aug 14 '14 at 14:22
  • @SylvainLeroux: Point taken!! w.r.t. *ill formed* value, (1) is highly possible but targeting `"` or `'` should handle that corner. (2) is possible but unlikely according to possible values here that can be supplied. (3) is interesting and you are absolutely right - both cannot be true at the same time. Corrected in my original code. – MacUsers Aug 14 '14 at 15:26

7 Answers7

5

If you are just trying to remove the punctuation then you can do it as below....

# remove all punctuation
awk -F= '{print $2}' n.dat | tr -d [[:punct:]]

# only remove single and double quotes
awk -F= '{print $2}' n.dat | tr -d \''"\'

explanation:

tr -d \''"\' is to delete any single and double quotes.
tr -d [[:punct:]] to delete all character from the punctuation class

Sample output as below from 2nd command above (without quotes):

myenv
mydomain.net
mykeypem
Gryu
  • 2,102
  • 2
  • 16
  • 29
narendra
  • 1,278
  • 1
  • 7
  • 8
2

The problem is not with awk, but with bash. The single quote inside the gsub is closing the open quote so that bash is trying to parse the command awk with arguments !/^...gsub(/"|/,, ,, $2 and then an unmatched close paren. Try replacing the single quote with '"'"' (so that bash will properly terminate the string, then apply a single quote, then reopen another string.)

William Pursell
  • 204,365
  • 48
  • 270
  • 300
2

Is awk really a requirement? If not, why don't you use a simple sed command:

sed -rn -e "s/^[^#]+='(.*)'$/\1/p" \
        -e "s/^[^#]+=\"(.*)\"$/\1/p" \
        -e "s/^[^#]+=(.*)/\1/p" data

This might seems over engineered, but it works properly with embedded quotes:

sh$ cat data
ENVIRONMENT="myenv"
ENV_DOMAIN='mydomain.net'
LOGIN_KEY=mykey.pem
PASSWD="good ol'passwd"
sh$ sed -rn -e "s/^[^#]+='(.*)'/\1/p" -e "s/^[^#]+=\"(.*)\"/\1/p" -e "s/^[^#]+=(.*)/\1/p" data
myenv
mydomain.net
mykey.pem
good ol'passwd
Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
  • That is the only solution that works with quotes in the data. – martin Aug 14 '14 at 14:21
  • 1
    In the case of quotes mismatch (i.e. `ENV_DOMAIN='mydomain.net"`) this doesn't remove the quotes. If that's an issue, you might want to consider `sed -rn -e "s/^[^#]+=(\"|')(.*)(\"|')$/\2/p" file` – Aserre Aug 14 '14 at 14:43
1

You can use awk like this:

awk -F "=['\"]?|['\"]" '{print $2}' file
myenv
mydomain.net
mykey.pem
anubhava
  • 761,203
  • 64
  • 569
  • 643
1

This will work with your awk

awk -F= '!/^(#|$)/ && /^ENVIRONMENT=/ {gsub(/"/,"",$2);gsub(q,"",$2); print $2}' q=\' file

It is the single quote in the expression that create problems. Add it to an variable and it will work.

Jotne
  • 40,548
  • 12
  • 51
  • 55
0

I did the following:

awk -F"=\"|='|'|\"|=" '{print $2}' file
myenv
mydomain.net
mykey.pem

This tells awk to use either =", =', ' or " as field separator.

martin
  • 3,149
  • 1
  • 24
  • 35
  • if you have a line with comment (or any text) containing a quote, some of it will be displayed – Aserre Aug 14 '14 at 14:08
  • Yes, similar to some of the other solutions, it works only if no quotes are in the string. The only one that works correctly is that of Sylvain. – martin Aug 14 '14 at 14:20
0

This is because the awk program must be enclosed in single quotes when run as a command line program. The program can be tripped up if a single quote is contained inside the script. Special tricks can be made to use single quotes as strings inside the program. See Shell-Quoting Issues in the GNU Awk Manual.

One trick is to save the match string as a variable:

awk -F\= -v s="'|\"" '{gsub(s, "", $2); print $2}' file

Output:

myenv
mydomain.net
mykey.pem
John B
  • 3,566
  • 1
  • 16
  • 20