Tengo una tabla con columnas. En la primera columna, tengo la hora en que el usuario inició sesión, en la segunda columna, tengo el nombre del usuario.
13:15:39 fxs1cia1qulm1lk
13:15:39 fxs1cia1qulm1lk
13:15:39 fxs1cia1qulm1lk
13:15:42 faaaa2aa11111
13:15:49 terd1sfsd11fsdf
13:15:49 terd1sfsd11fsdf
13:15:49 terd1sfsd11fsdf
13:15:59 21erdsf123sdfsdf
13:15:59 21erdsf123sdfsdf
13:15:59 21erdsf123sdfsdf
13:15:59 21erdsf123sdfsdf
13:17:50 abcasbbabadab
13:17:50 abcasbbabadab
13:17:50 abcasbbabadab
13:17:50 abcasbbabadab
13:19:19 fxs1ce1iulmla
13:19:19 fxs1ce1iulmla
13:19:19 fxs1ce1iulmla
13:20:42 faaa2a0a1111
Entonces, ¿qué debo hacer? Debería realizar una actualización única con estas dos columnas, y si la hora de inicio de sesión del usuario y el nombre del usuario son iguales, debo decir que ese usuario ha iniciado sesión más de 3 veces. He escrito un guión corto:
log_file=/root/log
temp_file=/root/temp
temp_file2=/root/temp2
cat /dev/null > $temp_file
cat /dev/null > $temp_file2
cat /dev/null > $result_file
cat $log_file | awk '{print $1}' | tail -n 20 > $temp_file
cat $log_file | awk '{print $5}' | tail -n 20 > $temp_file2
for i in `uniq -c $temp_file | awk '{print $1}'`; do
for y in `uniq -c $temp_file2 | awk '{print $2}'`; do
if [ $i -gt 3 ] && [ $y -gt 3 ]; then
s=`uniq -c $temp_file2 | awk '$1 == '$i`
echo "The user $s has logged more than 3 times"
fi
done
done
Por favor, comprueba, ¿qué te parece? ¿Este script es correcto? Porque, después de la salida de mi script en eco, tengo eso:
The user 4 21erdsf123sdfsdf
4 abcasbbabadab has logged more than 3 times
The user 4 21erdsf123sdfsdf
4 abcasbbabadab has logged more than 3 times
The user 4 21erdsf123sdfsdf
4 abcasbbabadab has logged more than 3 times
The user 4 21erdsf123sdfsdf
4 abcasbbabadab has logged more than 3 times
Pero quiero tener un resultado como este:
The user 4 21erdsf123sdfsdf has logged more than 3 times
The user 4 abcasbbabadab has logged more than 3 times
Y eso es todo. ¿Dónde tengo un error? Por favor ayuda.
Respuesta1
Puedes hacer esto de una manera muy sencilla conawk
awk '{ users[$2]++ }
END {
for (user in users)
if (users[user] > 1)
printf "%s logged in %d times\n", user, users[user]
}' < /root.log
Este programa escanea el root.log creando una matriz asociativa (también conocida como hash) con los recuentos de cada usuario y luego imprime los que son mayores que uno.
Respuesta2
Entonces, ¿el único problema es que imprime el mismo resultado varias veces? ¿Por qué no simplemente pasar por uniq? ¿Volcar a otro archivo temporal y luego ejecutar uniq en él?
Si eso no es lo que estás preguntando, tengo algunas observaciones:
- trabajar con datos separados en línea en bash/sh suele ser más problemático de lo que vale la pena. A menos que la solución sea obvia, busque un lenguaje de programación en el que no tenga que manipular IFS todo el tiempo. (Si no sabe cuál es la var IFS, realmente recomiendo mantenerse alejado de bash/sh para datos separados por líneas).
- Como ya estás usando awk, apuesto a que podrías hacer todo como un script awk.
- Dado que las líneas que le preocupan son idénticas, puede hacerlo
sort logfile | uniq -c
. - No estás ordenando tu archivo antes de uniq, por lo que uniq no funcionará si las líneas idénticas no están una al lado de la otra. Por ejemplo, si Bob y Joe inician sesión al mismo tiempo y sus entradas de registro se alternan.
- siempre hay grep -c
- lea sobre el comando de clasificación, especialmente -d, -n, -k y -t
ACTUALIZAR
¿Está pidiendo consejo sobre scripts de shell o está buscando una respuesta práctica a la pregunta de cómo puedo saber quién está actualmente conectado a 3 o más sesiones?
consejos de secuencias de comandos:
- Estoy bastante seguro
$s
de que contiene toda la cadena,4 21erdsf123sdfsdf <newline> 4 abcasbbabadab
incluida una nueva línea. No puedo entender muy bien por qué. - Por qué lo haces
awk '{print $5}'
? Intenté copiar los datos de tu ejemplo y ejecutarlosawk '{print $5}'
y obtuve un montón de nuevas líneas y nada más. - ¿Has mirado el contenido de
$temp_file
y$temp_file2
para asegurarte de que sea lo que esperabas? - Me dice
tail -n 20
que solo quieres entradas "recientes" y no te importa cuán recientes sean. ¿Es esto cierto? - Las
cat /dev/null > $file
líneas son redundantes, simplemente elimínelas. - Reemplace el
cat $logfile
consort $logfile
- Sangra tus bucles
Básicamente, este script no hará lo que usted desea y no puedo decir cómo pretendía que funcionara, por lo que no puedo darle consejos más específicos. Lo siento.
práctico
- use el script awk de @greg-tarsa ('disculpas, Greg, cariño, no sé cómo vincular a un usuario que tiene un espacio en su nombre)
- ¿Estás hablando de inicios de sesión actuales en un sistema Unix? ¿Has probado el
who
comando? ¿EGwho | awk '{ print $1}' | sort | uniq -c | sort -d -r
o ellast
comando? - busque la respuesta a su pregunta general (¿cómo puedo saber quién ha iniciado sesión/ha iniciado sesión demasiadas veces) en lugar de la pregunta más específica que está bloqueando la solución que ya está intentando implementar (Uniq por dos columnas con dos condiciones) . Si está más interesado en practicar sus scripts de shell, haga su pregunta de una manera que lo diga.