0

I have a text file which contains the following lines:

"user","password_last_changed","expires_in"
"jeffrey","2021-09-21 12:54:26","90 days"
"root","2021-09-21 11:06:57","0 days"

How can I grab two fields jeffrey and 90 days from inverted commas and save in a variable.

Cyrus
  • 84,225
  • 14
  • 89
  • 153
  • You probably want a regex. What should the output look like, exactly? – cornuz Sep 26 '21 at 08:57
  • If grep is facultative, try var=$(cut -d',' -f 1,3 < txt) echo "${var}" – nissim abehcera Sep 26 '21 at 09:04
  • 2
    Inverted commas? You mean double quotes? – Shawn Sep 26 '21 at 10:03
  • `xargs` maybe what you want, It let your handle lines one by one. Your question is not very clear, please clarify it. What do you mean by "inverted comma"? What are you trying to do? does those two column really need to be captured inside variables? – unifreak Sep 26 '21 at 10:38
  • @Jamal Hossain : I have answered your question. Please check if this fulfil your need – codeholic24 Oct 03 '21 at 16:39
  • If you want a truly compliant CSV parser, you'd do better to use Python than bash. The various answers here all have corner cases where they can be wrong when using sufficiently interesting CSV files. – Charles Duffy Oct 03 '21 at 16:39

4 Answers4

0
IFS=","

arr=( $(cat txt | head -2 | tail -1  | cut -d, -f 1,3 | tr -d '"') )
echo "${arr[0]}"
echo "${arr[1]}"

The result is into an array, you can access to the elements by index.

Cyrus
  • 84,225
  • 14
  • 89
  • 153
nissim abehcera
  • 821
  • 6
  • 7
  • Note that `cat txt | something` is better replaced with ` – Charles Duffy Oct 03 '21 at 16:40
  • (`tail` is not the only tool that gets much less efficient when given a pipeline as input instead of a real file handle; `wc -c`, `sort`, and `tac` are three more examples that come to mind offhand) – Charles Duffy Oct 03 '21 at 16:42
0
while read -r line; do # read in line by line
    name=$(echo $line | awk -F, ' { print $1} ' | sed 's/"//g') # grap first col and strip "
    expire=$(echo $line | awk -F, ' { print $3} '| sed 's/"//g') # grap third col and strip "
    echo "$name" "$expire" # do your business
done < yourfile.txt
unifreak
  • 773
  • 6
  • 17
  • This is both buggy and inefficient. Buggy because `echo $line` can echo a list of filenames if your file contains `*` as a line. Inefficient because it's starting at least six subprocesses for every line of input when there's no reason to start _any_ at all. (Every time you run `name=$(echo $line | awk | sed)`, the shell `fork()`s off a subshell to run the `echo`; another subshell to `exec awk`, and another subshell to `exec sed`; spawning external processes is one of the slowest things a shell can do, and reliance on them is part of why shell scripts have such a reputation for being slow). – Charles Duffy Oct 03 '21 at 16:54
0

If awk is an option, you could save an array and then save the elements as individual variables.

$ IFS="\"" read -ra var <<< $(awk -F, '/jeffrey/{ print $1, $NF }' input_file)
$ $ var2="${var[3]}"
$ echo "$var2"
90 days
$ var1="${var[1]}"
$ echo "$var1"
jeffrey
HatLess
  • 10,622
  • 5
  • 14
  • 32
0

May be this below method will help you using sed and awk command

#!/bin/sh
username=$(sed -n '/jeffrey/p' demo.txt | awk -F',' '{print $1}')
echo "$username"

expires_in=$(sed -n '/jeffrey/p' demo.txt | awk -F',' '{print $3}')
echo "$expires_in"

Output :

jeffrey
90 days

Note : This above method will work if their is only distinct username As far i know username are not duplicate

codeholic24
  • 955
  • 4
  • 22
  • There are some places where this code is not good practice. `echo $var` should always be `echo "$var"` -- see [I just assigned a variable, but `echo $variable` shows something else!](https://stackoverflow.com/questions/29378566/i-just-assigned-a-variable-but-echo-variable-shows-something-else) – Charles Duffy Oct 03 '21 at 16:43
  • Also, backticks should be avoided in favor of modern POSIX-compliant command substitution: `$(...)` can be easily nested, and doesn't change the meaning of backslashes and backticks inside the enclosed space. – Charles Duffy Oct 03 '21 at 16:44
  • @CharlesDuffy : Thanks for correcting me .. i tried on git bash that's a reason i given let me change it. Using shellcheck.in – codeholic24 Oct 03 '21 at 16:45
  • 1
    Also, in general, it's better to avoid running two separate command substitutions -- you're running `sed` and `awk` twice as many times as you need to. Consider `IFS=$'\t' read -r username expires_in < <(awk -F, '/jeffrey/ { printf "%s\t%s\n", $1, $3 }')` to not need `sed` at all and run `awk` only once. – Charles Duffy Oct 03 '21 at 16:46
  • @CharlesDuffy : Thanks bro for letting me know that values can be assigned in one single line to multiple variables – codeholic24 Oct 03 '21 at 16:49
  • @CharlesDuffy : How about making use of `grep -Hno "jeffrey" demo.txt` can you provide your input – codeholic24 Oct 03 '21 at 16:52
  • `grep -o` is only going to output `jeffrey`, so that's clearly wrong. And the `-H` is used to write the filename, but the filename will only ever be `demo.txt`, so there's not a reason for that either. – Charles Duffy Oct 03 '21 at 16:56