简体   繁体   中英

Bash while loop with sudo and awk

I am trying to read a file using a while loop running as sudo, and then run some awk on each line. File owner is user2 and I am running as user1.

sudo sh -c 'while IFS= read -r line; do
    echo $line | awk '{print $NF}'; done < /home/user2/test.txt'

I am having trouble with the single quotes. Double quotes does not work at both the places where I have single quotes. Is there any way to get the same command to work with some adjustments?

NOTE: I got the output using the following methods:

  •  sudo cat /home/user2/test.txt | while IFS= read line; do echo $line | awk '{print $NF}' done
  •  sudo awk {'print $NF'} /home/user2/test.txt

I am trying to understand if there is any solution for using sudo, while and awk with single quotes all of them in a single line.

There are a few reasonable options:

sudo sh -c 'while IFS= read -r line; do echo "$line" | awk '"'"'{print $NF}'"'"';done < /home/user2/test.txt'

or (observing that this particular awk does not require single quotes):

sudo sh -c 'while IFS= read -r line; do echo "$line" | awk "{print \$NF}"; done < /home/user2/test.txt'

or (always a good choice to simplify things) write a script:

sudo sh -c '/path/to/script'

or:

sudo sh << \EOF
while IFS= read -r line; do echo "$line" | 
    awk '{print $NF}'; done < /home/user2/test.txt
EOF

Note that for all of these it would be good to get rid of the loop completely and do:

sudo sh -c 'awk "{printf \$NF}" /home/user2/test.xt'

but presumably this is a simplified version of the actual problem

You should definitely only use sudo for the code which absolutely needs the privileges. This would perhaps be one of the very few cases where a single cat makes sense.

sudo cat /home/user2/test.txt | awk '{ print $NF }'

As others have noted already, the while read loop is completely useless and quite inefficient here, but if you really insist on doing something like that, it's not hard to apply the same principle. (Notice also the fixed quoting. )

sudo cat /home/user2/test.txt |
while IFS= read -r line; do
    echo "$line"   # double quotes are important
done | awk '{ print $NF }'

Tangentially, you cannot nest single quotes inside single quotes. The usual solution to that is to switch one set of quotes to double quotes, and probably also then correspondingly escape what needs escaping inside the double quotes.

sudo sh -c 'while IFS= read -r line; do
       echo "$line" | awk "{print \$NF}"
       # double quotes and^ escape^    ^
    done < /home/user2/test.txt'

Just to spell this out, the double quotes around the Awk script are weaker than single quotes, so the dollar sign in $1 needs to be backslashed to protect it from the (inner) shell.

... But as suggested above, the awk script doesn't need to run inside sudo at all here; and anyway, it's also more efficient to put it outside the done .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM