1

I have a file with this content:

$ cat init
Sample text
PM1:alex:1.2.3.4:22:passwordPM
PM2:alice:5.6.7.8:1212:Password
PM3:bob:9.10.11.12:1313:p@ssword
Some other text

Now I want to grep PM1 to PM3 and I want to set some variables and use them in my script:

user1="alex"
ip1="1.2.3.4"
port1="22"
pass1="password"
...

I need an structure could be used in more than PM1 to PM3. may be I have also PM10.

It's clear that we can grep each field but I don't know how we can use them.

grep PM init | cut -d: -f2
grep PM init | cut -d: -f3
grep PM init | cut -d: -f4
# I need to grep field number 5 in this way:
grep PM init | cut -d: -f5-

Update

I need to grep PM if the third letter is number. because if I don't do it may mixed up with passwords(last field).

M.J
  • 315
  • 3
  • 9
  • It is much easier to do this in `awk` since data in row & column based using a common delimiter – anubhava Jun 30 '20 at 06:12
  • `user1` is always `user1` it does not increment the number on it? – Jetchisel Jun 30 '20 at 06:24
  • 1
    @Jetchisel user{number} ip{number} port{number} pass{number}, all should inherits PM{number} – M.J Jun 30 '20 at 06:26
  • Does this answer your question? [How do I set a variable to the output of a command in Bash?](https://stackoverflow.com/questions/4651437/how-do-i-set-a-variable-to-the-output-of-a-command-in-bash) – kvantour Jun 30 '20 at 06:58

2 Answers2

2

A slow if not the slowest bash shell solution for large data/size files.

#!/usr/bin/env bash

while read -r lines; do
  if [[ $lines == PM[0-9]* ]]; then
    IFS=: read -r pm user ip port pass <<< "$lines"
    n=${pm#*??}
    printf -v output 'user%s="%s"\nip%s="%s"\nport%s="%s"\npass%s="%s"' "$n" "$user" "$n" "$ip" "$n" "$port" "$n" "$pass"
    array+=("$output")
  fi
done < init

printf '%s\n' "${array[@]}"

The array can be separated in one line per entry, since the current solution groups the assignment and values per PM[0-9]*, if you loop over the array it should show what I'm talking about.

for i in "${array@]}"; do
  echo "$i"
  echo
done

Here is the separate entry for the array value and assignments, which can replace the current array structure depending on what you're doing.

printf -v user 'user%s="%s"' "$n" "$user"
printf -v ip 'ip%s="%s"' "$n" "$ip"
printf -v port 'port%s="%s"' "$n" "$port"
printf -v pass 'pass%s="%s"' "$n" "$pass"
array+=("$user" "$ip" "$port" "$pass")
Jetchisel
  • 7,493
  • 2
  • 19
  • 18
1

A single sed command would do it (using GNU sed, inputfile is to be replaced with the actual input file name):

sed -E -n 's/^PM([0-9]+):([^:]*):([^:]*):([^:]*):(.*)/user\1="\2"\nip\1="\3"\nport\1="\4"\npass\1="\5"/p' inputfile

outputs

user1="alex"
ip1="1.2.3.4"
port1="22"
pass1="passwordPM"
user2="alice"
ip2="5.6.7.8"
port2="1212"
pass2="Password"
user3="bob"
ip3="9.10.11.12"
port3="1313"
pass3="p@ssword"

You can embed these generated variables in your script like that:

#!/bin/bash

# Generate name=value pairs from inputfile and save them in a temporary file /tmp/variables
sed -E -n 's/^PM([0-9]+):([^:]*):([^:]*):([^:]*):(.*)/user\1="\2"\nip\1="\3"\nport\1="\4"\npass\1="\5"/p' inputfile > /tmp/variables || exit

# "Source" the file into script 
. /tmp/variables
# Temporary file is not needed any longer. You can remove it if you want

# You can use generated variable names from now on:
echo "user1=$user1"
# and the like
M. Nejat Aydin
  • 9,597
  • 1
  • 7
  • 17