How to echo a string after sorting it by maximum length - bash

so I am just learning bash and right now I am trying to write one line codes to solve some problems. So write now I am listing all the users in stampede and trying to get the length and name of the longest string.
So this is where I am at
getent passwd | cut -f 1 -d: | wc -L
getent passwd - (too get the userid list), the cut command to get the first userid and then wc -L to get the longest length. Now I am trying to figure out how do I echo that? So any input on that would be awesome thank you!

To get the name of the user with the longest name, use:
getent passwd | awk -F: '{longest=length($1)>length(longest)?$1:longest} END{print longest}'
How it works
-F:
Tell awk to use a colon as the field separator.
longest=length($1)>length(longest)?$1:longest
For every line of input, this statement is executed. It assigns to the variable longest the result of a ternary statement:
length($1)>length(longest)?$1:longest
This statement tests the condition length($1)>length(longest). Here, length($1) is the length of the name of the current user and length(longest) is the length of the longest name seen previously. If the current name is longer, the ternary expression returns the current name, $1. Otherwise, it returns the previous longest name, longest.
END{print longest}
After we have finished reading the file, this prints the name that was the longest.

One way to do this, that doesn't stray too far from what you have, is to use sed to only output lines that are at least as long as the length you get from your command above:
getent passwd | cut -f 1 -d: | sed -n /^.\\{`getent passwd | cut -f 1 -d: | wc -L`\\}/p
This will output all users which tie for the longest length.
You can make it a little nicer by storing the list of names in a variable:
u=`getent passwd | cut -f 1 -d:`; sed -n /^.\\{`wc -L <<< "$u"`\\}/p <<< "$u"

Another way of doing it:
getent passwd | cut -f 1 -d: | perl -ne 'print length($_).":$_"'| sort -n| cut -f 2 -d:
We create a list <length>:<username> with perl, sort by length and print only username.

Related

Bash Script - get User Name given UID

How - given USER ID as parameter, find out what is his name? The problem is to write a Bash script, and somehow use etc/passwd file.
The uid is the 3rd field in /etc/passwd, based on that, you can use:
awk -v val=$1 -F ":" '$3==val{print $1}' /etc/passwd
4 ways to achieve what you need:
http://www.digitalinternals.com/unix/linux-get-username-from-uid/475/
Try this:
grep ":$1:" /etc/passwd | cut -f 1 -d ":"
This greps for the UID within /etc/passwd.
Alternatively you can use the getent command:
getent passwd "$1" | cut -f 1 -d ":"
It then does a cut and takes the first field, delimited by a colon. This first field is the username.
You might find the SS64 pages for cut and grep useful:
http://ss64.com/bash/grep.html
http://ss64.com/bash/cut.html

Shell cut delimiter before last

I`m trying to cut a string (Name of a file) where I have to get a variable in the name.
But the problem is, I have to put it in a shell variable, until now it is ok.
Here is the example of what i have to do.
NAME_OF_THE_FILE_VARIABLEiWANTtoGET_DATE
NAMEfile_VARIABLEiWANT_DATE
NAME_FILE_VARIABLEiWANT_DATE
The position of the variable I want always can change, but it will be always 1 before last. The delimiter is the "_".
Is there a way to count the size of the array to get size-1 or something like that?
OBS: when i cut strings I always use things like that:
VARIABLEiWANT=`echo "$FILENAME" | cut 1 -d "_"`
awk -F'_' '{print $(NF-1)}' file
or you have a string
awk -F'_' '{print $(NF-1)}' <<< "$FILENAME"
save the output of above oneliner into your variable.
IFS=_ read -a array <<< "$FILENAME"
variable_i_want=${array[${#array[#]}-2]}
It's a bit of a mess visually, but it's more efficient than starting a new process. ${#array[#]} is the number of elements read from FILENAME, so the indices for the array range from 0 to ${#array[#]}-1.
As of bash 4.3, though, you can use a negative index instead of computing it.
variable_i_want=${array[-2]}
If you need POSIX compatibility (no arrays), then
tmp=${FILENAME%_${FILENAME##*_}} # FILENAME with last field removed
variable_i_want=${tmp##*_} # last field of tmp
Just got it... I find someone using a cat function... I got to use it with the echo... and rev. didn't understand the rev thing, but I think it revert the order of the delimiter.
CODIGO=`echo "$ARQ_NAME" | rev | cut -d "_" -f 2 | rev `

How to compare a file to a list in linux with one line code?

Hey so got another predicament that I am stuck in. I wanted to see approximately how many Indian people are using the stampede computer. So I set up an indian txt file in vim that has about 50 of the most common surnames in india and I want to compare those names in the file to the user name list.
So far this is the code I have
getent passwd | cut -f 5 -d: | cut -f -d' '
getent passwd gets the userid list which is going to look like this
tg827313:x:827313:8144474:Brandon Williams
the cut functions will get just the last name so the output of the example will be
Williams
Now can use the grep function to compare files but how do I use it to compare the getent passwd list with the file?
To count how many of the last names of computer users appear in the file namefile, use:
getent passwd | cut -f 5 -d: | cut -f -d' ' | grep -wFf namefile | wc -l
How it works
getent passwd | cut -f 5 -d: | cut -f -d' '
This is your code which I will assume works as intended for you.
grep -wFf namefile
This selects names that match a line in namefile. The -F option tells grep not to use regular expressions for the names. The names are assumed to be fixed strings. The option -f tells grep to read the strings from file. -w tells grep to match whole words only.
wc -l
This returns a count of the lines in the output.

How to temporarily sort a file from longest to shortest line, before restoring it back to its original order?

The answers in Sorting lines from longest to shortest provide various ways to sort a file's lines from longest to shortest.
I need to temporarily sort a file from longest to shortest, to give some time for a BASH script to perform some operations to edit various content, but then to restore the file to its original order after the BASH script has finished.
How can I first sort a file from longest to shortest, but then be able to restore the order later?
Done by enhancing your linked answer by these steps:
Prepend a length and line number to the front of each line, sort by length, cut length (just like in linked answer)
perl -ne 'print length($_)." $. $_"' file.txt | sort -r -n | cut -d ' ' -f 2- > newfile.txt
Do your bash translation (ignoring first number on each line)
If for some reason you can't do your amorphous translation with the number prefixes, then split the numbers into a separate file and merge them back in afterwords.
Sort by line number and then cut off line number to restore file to previous state.
sort -n newfile.txt | cut -d ' ' -f 2- > file.txt
Something like this to store the original line order in a separate file might be what you need:
awk -v OFS='\t' '{print length($0), NR, $0}' infile |
sort -k1rn -k2n |
tee order.txt |
cut -f3- > sorted.txt
do stuff with sorted.txt then
cut -f2 order.txt |
paste - sorted.txt |
sort -n |
cut -f2- > outfile
You don't say what you want done with lines that are the same length as each other but the above will preserve the order from the original file in that case. If that's not what you want, play with the sort -rn commands, modifying the -ks as necessary.

Append xargs argument number as prefix

I want to analyze the most frequentry occuring entries in (column of) a logfile. To write the detail results, I am creating new directories from the output of something along the lines of
cat logs| cut -d',' -f 6 | sort | uniq -c | sort -rn | head -10 | \
awk '{print $2}' |xargs mkdir -p
Is there a way to create the directories with the sequence number of the argument as processed by xargs as a prefix? For e.g. For e.g. "oranges" is the most frequent entry (of the column) the directory created should be named "1.oranges" and so on.
A quick (and dirty?) solution could be to pipe your directory names through cat -n in their proper order and then remove the whitespace separating the line number from the directory name, before passing them to xargs.
A better solution would be to modify your awk command:
... | awk '{ print NR "." $2 }' | xargs mkdir -p
The NR variable contains the record (i.e. line) number.

Resources