parsing /etc/passwd with awk command without making a output file for every line and reading from there - bash

I need to parse the /etc/passwd file in the most efficient way
I know I can use the command cat /etc/passwd | awk -F: '{print $1}' but it gets everything in the row, how can I narrow the column so it only gets one input?
I can also make an output file for every row and read from that but that seems like it is ineffective.
edit: so for example, I only need one username from the /etc/passwd file
as
user: x
gid: y

It's not quite clear what kind of parsing you want to do, but perhaps cut is the command you're looking for. For example, if you want to get all the usernames and homes you could do this:
cut -d: -f1,6 /etc/passwd
Check the cut man page for more details.

Related

How to get '2f8b547d..eb94967a' string from the log 'Updating 2f8b547d..eb94967a Fast-forward....' in shell?

I am building a shell script.
The script gets git log such as:
"Updating 2f8b547d..eb94967a Fast-forward...."
but I want to get 2f8b547d..eb94967a snippet.
I am a new one for the shell. So, Thanks for you help.
Update:
For the more, I want use the snippet as a param. Because I will excute
git log 2f8b547d..eb94967a
You can pipe it to awk like so:
echo "Updating 2f8b547d..eb94967a Fast-forward...." | awk '{print $2}'
Your result will be 2f8b547d..eb94967a.
If it is a script, say, abc.sh that had such output, then you can run:
$> ./abc.sh | awk '{print $2}'
awk takes the output and splits the information by space. Updating is represented with $1. 2f8b547d..eb94967a is $2 and so on. In the above example, we ask awk to print out the 2nd item in the output.
As an alternative to awk (don't get me wrong, awk is super for this job as well), you can simply use cut with a space delimiter extract the second field, e.g.
cut -d' ' -f2 yourgit.log
You can also pipe output to cut or redirect the input file to it using < as well. It essentially does the same as the awk command, it just being a different choice of which utility to use.
Here another alternative:
echo "Updating 2f8b547d..eb94967a Fast-forward...." | read u hash rest
After this, the string you are looking for is stored on the variable hash:
echo $hash

Filter awk system output with awk?

I need to use awk to see what users are logged in the computer, create a file with their names and inside that file print the pid of the process they're running. I've used this, but it does not work:
who | awk '{for(i = 0; i < NR; i++)
system("ps -u " $1 "| tail +2 | awk '{print $1}' >" $1".log")
}'
Is there any way to do this?
Thanks a lot!
To achieve your goal of using awk to create those files, I would start with ps rather than with who. That way, ps does more of the work so that awk can do less. Here is an example that might work for you. (No guarantees, obviously!)
ps aux | awk 'NR>1 {system("echo " $2 " >> " $1 ".txt")}'
Discussion:
The command ps aux prints a table describing each active process, one line at a time. The first column of each line contains the name of the process's user, the second column its PID. The line also contains lots of other information, which you can play with as you improve your script. That's what you pipe into awk. (All this is true for Linux and the BSDs. In Cygwin, the format is different.)
Inside awk, the pattern NR>1 gets rid of the first line of the output, which contains the table headers. This line is useless for the files you want awk to generate.
For all other lines in the output of ps aux, awk adds the PID of the current process (ie, $2) to the file username.txt, using $1 for username. Because we append with >> rather than overwriting with >, all PIDs run by the user username end up being listed, one line at a time, in the file username.txt.
UPDATE (Alternative for when who is mandatory)
If using who is mandatory, as noted in a comment to the original post, I would use awk to strip needless lines and columns from the output of who and ps.
for user in $(who | awk 'NR>1 {print $1}')
do
ps -u "$user" | awk 'NR>1' > "$user".txt
done
For readers who wonder what the double-quotes around $user are about : Those serve to guard against globbing (if $user contains asterisks (*)) and word splitting (if $user contains whitespace).
I will leave my original answer stand for the benefit of any readers with more freedom to choose the tools for their job.
Is that what you had in mind?

Making bash output a certain word from a .txt file

I have a question on Bash:
Like the title says, I require bash to output a certain word, depending on where it is in the file. In my explicit example I have a simple .txt file.
I already found out that you can count the number of words within a file with the command:
wc -w < myFile.txt
An output example would be:
78501
There certainly is also a way to make "cat" to only show word number x. Something like:
cat myFile.txt | wordno. 3125
desired-word
Notice, that I will welcome any command, that gets this done, not only cat.
Alternatively or in addition, I would be happy to know how you can make certain characters in a file show, based on their place in it. Something like:
cat myFile.txt | characterno. 2342
desired-character
I already know how you can achieve this with a variable:
a="hello, how are you"
echo ${a:9:1}
w
Only problem is a variable can only be so long. Is it as long as a whole .txt file, it won't work.
I look forward to your answers!
You could use awkfor this job it splits the string at spaces and prints the $wordnumber stringpart and tr is used to remove newlines
cat myFile.txt | tr -d '\n' | awk -v wordnumber=5 '{ print $wordnumber }'
And if you want the for example 5th. character you could do this like so
head -c 5 myFile.txt | tail -c 1
Since you have NOT shown samples of Input_file or expected output so couldn't test it. You could simply do this with awk as follows could be an example.
awk 'FNR==1{print substr($0,2342,1);next}' Input_file
Where we are telling awk to look for 1st line FNR==1 and in substr where we tell awk to take character 2342 and next 1 means from that position take only 1 character you could increase its value or keep it as per your need too.
With gawk:
awk 'BEGIN{RS="[[:space:]]+"} NR==12345' file
or
gawk 'NR==12345' RS="[[:space:]]+" file
I'm setting the record separator to a sequences of spaces which includes newlines and then print the 12345th record.
To improve the average performance you can exit the script once the match is found:
gawk 'BEGIN{RS="[[:space:]]+"}NR==12345{print;exit}' file

Organising a result query

I am trying to write a program (either python or bash) to extract saved passwords from the chromium web browser.
What I've found so far, the following command extracts the web site address, username and password:
$ sqlite3 ~/.config/chromium/Default/"Login Data" "select * from logins" | cut -d "|" -f 1,4,6
The data however is displayed on the screen and not neatly organised. What I am trying to do is store the data neatly.
The output is at the moment delimited by a | , instead I'd like this delimited by a tab (\t)
I'd like to prefix a header on top
The first column has http:// or https:// preceding the website address, I'd like that stripped.
If possible I'd like to be able to contain all that in a single script. If bash is ill suited for this, I am willing to try different programming language as required.
Any other suggestions are most welcome because I'm doing this as a hobby. The more I get to learn the better.
I am looking for suggestions on what I can do. Upon my last thread I was suggested to post on codereview stack exchange site instead for suggestion. If this is also better suited there forgive my noobness, and if possible tell me how I could move this.
Assuming you saved the results of your query in a file called /path/to/file:
$ cat script
#!/bin/bash
sed -i '1iURL|Username|Password' /path/to/file
sed -i 's|http.*//||g' /path/to/file
awk -F"|" '{ print $1, $2, $3 }' /path/to/file | column -t > /path/to/output
This should do it.
Line1: sed -i '1iURL|Username|Password' /path/to/file: Adds header to your file
Line2: sed -i 's|http.*//||g' /path/to/file: Strips the http*// from your file
Line3: awk -F"|" '{ print $1, $2, $3 }' /path/to/file | column -t > /path/to/output: formats the output to a new file: /path/to/output

bash - get usernames from command last output

I need to get all users from file, containing information about all loggins within some time interval. (The delimiter is : )
So, I need to get all users from output of command last -f.
I tried to do this:
last -f file| cut -d ":" -f1
but in the output aren't just the usernames. It seems to me like some record take more than just one line and therefore it can't distinguish the records. I don't know.
Could you help me please? I would be grateful for any advice.
You could say:
last -f file | awk '{print $1}'
If you want to use cut, say:
last -f file| cut -d " " -f1

Resources