Home > database >  awk upon regex match, read from the end of each line and print everything up until '/' for
awk upon regex match, read from the end of each line and print everything up until '/' for

Time:05-28

I'm writing a script to get a list of only the commands from my crontab. My input data so far looks like this:

$  crontab -l | grep -i --color -v '^#' | awk '$0 ~ /^*\/[0-9]{1,20}|\* /'
*/5 * * * * /usr/local/bin/bash msmtp-queue -r 
*/5 * * * * /usr/bin/env bash /Users/tonybarganski/bin/offlineimap-fetch
*/15 * * * * /usr/bin/env bash ~/bin/checkMail
00 12 * * * /usr/local/bin/bash ~/bin/lbdb-fetchaddress-daily
* */3 * * * /usr/bin/env rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log

Outcome

Print everything after either '/usr/bin/env bash' or '/usr/local/bin/bash' or '* */3 * * *'

msmtp-queue -r 
offlineimap-fetch
checkMail
lbdb-fetchaddress-daily
rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log

Tried

I tried starting from the end of file ($NF) and printing everything up until the first forward slash but I just got syntax errors with where to put the brackets:

$ crontab -l | grep -i --color -v '^#' | \
awk -F'/' '{ if ($0 ~ /^*\/[0-9]{1,20}|\* /) for(i=NF;i>0;i--) { if ( sub(/\//, "", $i) { print $i} } }'
awk: cmd. line:1: { if ($0 ~ /^*\/[0-9]{1,20}|\* /) for(i=NF;i>0;i--) { if ( sub(/\//, "", $i) { print $i} } }
awk: cmd. line:1:                                                                              ^ syntax error

How can this be achieved?

CodePudding user response:

get a list of only the commands from my crontab

I would just jettison 5 first fields, let file.txt content be

*/5 * * * * /usr/local/bin/bash msmtp-queue -r 
*/5 * * * * /usr/bin/env bash /Users/tonybarganski/bin/offlineimap-fetch
*/15 * * * * /usr/bin/env bash ~/bin/checkMail
00 12 * * * /usr/local/bin/bash ~/bin/lbdb-fetchaddress-daily
* */3 * * * /usr/bin/env rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.lo

then

awk 'BEGIN{FS=OFS=" "}{$1=$2=$3=$4=$5="";sub(/^ */,"");print}' file.txt

gives output

/usr/local/bin/bash msmtp-queue -r
/usr/bin/env bash /Users/tonybarganski/bin/offlineimap-fetch
/usr/bin/env bash ~/bin/checkMail
/usr/local/bin/bash ~/bin/lbdb-fetchaddress-daily
/usr/bin/env rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.lo

Explanation: I inform GNU AWK that field separator (FS) and output field separator (OFS) is single space. I do not use default FS as it would cause changing tab characters to space characters to space and compressing spaces (2 or more consecutive spaces into single space). For each line I set 1st, 2nd, 3rd, 4th and 5th field to empty string, then use sub to shave off leading spaces, then print such altered line.

(tested in GNU Awk 5.0.1)

CodePudding user response:

If you want to

Print everything after either '/usr/bin/env bash' or '/usr/local/bin/bash' or '* */3 * * *'

and given the format of the examples, you can split on the different patterns and check if there are at least 2 parts.

If file contains the example data:

awk '
{
  n = split($0,a, /(^\* \*\/3 \* \* \*|\/usr\/local\/bin\/bash|\/usr\/bin\/env[[:space:]] bash)[[:space:]] /)
  if (n > 1) {
    print a[2]
  }
}
' file

Output

msmtp-queue -r 
/Users/tonybarganski/bin/offlineimap-fetch
~/bin/checkMail
~/bin/lbdb-fetchaddress-daily
/usr/bin/env rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log

CodePudding user response:

Using sed (if applicable)

$ sed s'/.*\(bin\/\|\/env \)\?bash \|.*\* //' input_file
msmtp-queue -r
/Users/tonybarganski/bin/offlineimap-fetch
~/bin/checkMail
~/bin/lbdb-fetchaddress-daily
/usr/bin/env rsync -auv -f- index.lock --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log

CodePudding user response:

$ awk -F"bash|env bash|env" '!/^#/ {print $2}' <(crontab -l)
 msmtp-queue -r 
 /Users/tonybarganski/bin/offlineimap-fetch
 ~/bin/checkMail
 ~/bin/lbdb-fetchaddress-daily
 rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log
  • Related