2

I have the following code snippet:

#!/bin/bash
IFS='\r\n'
vconsole="pts"
for entry in $(last -n 10)
do
        if [ -z $entry ]
        then
                continue
        fi
        if [ "$( echo $entry | grep -o 'pts')" == "$vconsole" ]
        then
                echo $entry
        fi
done

If I execute it I get:

oot     pts/0        85.XXX.XXX.138   F
oot     pts/0        85.XXX.XXX.138   Mo
oot     pts/1        85.XXX.XXX.138   Tue Ja
oot     pts/0        85.XXX.XXX.138   Tue Ja

I expected something like this:

root     pts/0        85.XXX.XXX.138   Fri Jan 15 11:19   still logged in
root     pts/0        85.XXX.XXX.138   Mon Jan 11 10:12 - 10:43  (00:31)
root     pts/1        85.XXX.XXX.138   Tue Jan  5 14:30 - 14:39  (00:08)
root     pts/0        85.XXX.XXX.138   Tue Jan  5 13:29 - 14:39  (01:10)

Why is the first Character cut of? Additionally, why is the end cut off seemingly random?

I am running this on a centos-release-7-9.2009.1.el7.centos.x86_64

1
  • 1
    there are quite a few issues in your original (all of which have been fixed in ilkkachu's answer). First, avoid using for i in $(command), see "Bash pitfall number 1". Next, grep -o 'pts' will only ever return either the exact string pts or nothing. So since vconsole="pts", the "$( echo $entry | grep -o 'pts')" == "$vconsole" is pointless and could be written as echo $entry | grep 'pts'. Neither is what you want, as ilkkachu explained, but still. – terdon Jan 15 at 12:42
7
IFS='\r\n'

This sets IFS to <backslash><letter r><backslash><letter n>, so the r in "root" and "Fri", and the n in "Mon" and "Jan" act as separators. You meant to use the ANSI C-quoting, $'...', which turns the backslash escapes to the actual control characters CR and LR, i.e.:

IFS=$'\r\n'

Note that you could also use

if [[ $entry = *pts* ]]; then...

to look for the string, but both that and the echo | grep would also match e.g. fields where pts is part of the username.

To avoid that, you could do something like this:

#!/bin/bash
last -n 10 | while read -r line; do
    read -r  user term whatever <<< "$line"
    if [[ $term = *pts* ]]; then
        echo "$line"
    fi
done
0

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.