1

In a shell script I need to assign the output of few values to different varialbes, need help please.

cat file1.txt  
uid: user1  
cn: User One  
employeenumber: 1234567  
absJobAction: HIRED  

I need to assign the value of each attribute to different variables so that I can call them them in script. For example uid should be assigned to a new variable name current_uid and when $current_uid is called it should give user1 and so forth for all other attributes.
And if the output does not contain any of the attributes then that attribute value should be considered as "NULL". Example if the output does not have absJobAction then the value of $absJobAction should be "NULL"


This is what I did with my array

#!/bin/bash  

IFS=$'\n'  
array=($(cat /tmp/file1.txt | egrep -i '^uid:|^cn:|^employeenumber|^absJobAction'))  

current_uid=`echo ${array[0]} | grep -w uid | awk -F ': ' '{print $2}'`  
current_cn=`echo ${array[1]} | grep -w cn | awk -F ': ' '{print $2}'`  
current_employeenumber=`echo ${array[2]} | grep -w employeenumber | awk -F ': ' '{print $2}'`  
current_absJobAction=`echo ${array[3]} | grep -w absJobAction | awk -F ': ' '{print $2}'`  

echo $current_uid  
echo $current_cn  
echo $current_employeenumber  
echo $current_absJobAction  

Output from sh /tmp/testscript.sh follows:

user1  
User One  
1234567  
HIRED  
11
  • I think you'd be better served doing some searching for beginner shell scripting. There are tons of resources available. This forum is more for help with specific questions. Commented Jul 25, 2017 at 14:55
  • @Gary_W I checked few notes, assigning single variable was pretty straight forward, but for multiple variable it was asked to use arrays, which I tried few things didnt work the way I wanted. I am beginner to these. Thanks anyways. Commented Jul 25, 2017 at 15:03
  • You should mention that in your post, show what you tried and what didn't work. As it is your question is too general. Commented Jul 25, 2017 at 15:27
  • If your input format is this simple, you should consider rewriting it with = instead of : and just sourcing the file. That is, make it uid=user1 and the assignments happen when you execute . file1.txt Commented Jul 25, 2017 at 15:31
  • @Binish. What have you tried so far..? Commented Jul 25, 2017 at 15:32

2 Answers 2

2
#!/usr/bin/env bash

# assuming bash 4.0 or newer: create an associative array
declare -A vars=( )

while IFS= read -r line; do      ## See http://mywiki.wooledge.org/BashFAQ/001
  if [[ $line = *": "* ]]; then  ## skip lines not containing ": "
    key=${line%%": "*}           ## strip everything after ": " for key
    value=${line#*": "}          ## strip everything before ": " for value
    vars[$key]=$value
  else
    printf 'Skipping unrecognized line: <%s>\n' "$line" >&2
  fi
done <file1.txt # or < <(ldapsearch ...)

# print all variables read, just to demonstrate
declare -p vars >&2

# extract and print a single variable by name
echo "Variable uid has value ${vars[uid]}"

Note that this must be run with bash yourscript, not sh yourscript.


By the way -- if you don't have bash 4.0, you might consider a different approach:

while IFS= read -r line; do
  if [[ $line = *": "* ]]; then
    key=${line%%": "*}
    value=${line#*": "}
    printf -v "ldap_$key" %s "$value"
  fi
done <file1.txt # or < <(ldapsearch ...)

will create separate variables of the form "$ldap_cn" or "$ldap_uid", as opposed to putting everything in a single associative array.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much, it worked. Instead of the file name i redirected the ldap search directly to the while loop and that too worked. I really appreciate what you did for me.
1

Here's a simple example of what you are trying to do that should get you started. It assumes 1 set of data in the file. Although a tad brute-force, I believe its easy to understand.

Given a file called file.txt in the current directory with the following contents (absJobAction intentionally left out):

$ cat file1.txt
uid: user1  
cn: User One  
employeenumber: 1234567  
$ 

This script gets each value into a local variable and prints it out:

# Use /bin/bash to run this script
#!/bin/bash

# Make SOURCEFILE a readonly variable.  Make it uppercase to show its a constant. This is the file the LDAP values come from.
typeset -r SOURCEFILE=./file1.txt

# Each line sets a variable using awk.
#  -F is the field delimiter.  It's a colon and a space.
#  Next is the value to look for.  ^ matches the start of the line.
#  When the above is found, return the second field ($2)
current_uid="$(awk -F': ' '/^uid/ {print $2}' ${SOURCEFILE})"
current_cn="$(awk -F': ' '/^cn/ {print $2}' ${SOURCEFILE})"
current_enbr="$(awk -F': ' '/^employeenumber/ {print $2}' ${SOURCEFILE})"
current_absja="$(awk -F': ' '/^absJobAction/ {print $2}' ${SOURCEFILE})"

# Print the contents of the variables.  Note since absJobAction was not in the file,
# it's value is NULL.
echo "uid: ${current_uid}"
echo "cn: ${current_cn}"
echo "EmployeeNumber: ${current_enbr}"
echo "absJobAction: ${current_absja}"
~                                     

When run:

$ ./test.sh
uid: user1  
cn: User One  
EmployeeNumber: 1234567  
absJobAction: 
$ 

4 Comments

That works, but it's really inefficient as opposed to just doing one pass and using shell builtins to read into multiple variables.
@Gary_W Thank you, it worked. Really appreciate your time and effort on this. One question on your script what if my output directly comes from ldap command and not from a file, what changes to be made on your script?
This is set up to get the values from a file as per your original spec. A rewrite would make it a whole new program, and in that case Mr. Duffy's solution already does the trick nicely.
One approach would be akin to: result=$(ldapsearch ...), and then current_uid=$(awk -F': ' '/^uid/ {print $2}' <<<"$result"). That said, there's quite a lot of performance overhead here not present when doing just one pass (every $() is forking off a subshell, every heredoc or herestring creates a temporary file, every awk call means an external binary needs to be linked and loaded after a process is forked for it, etc), so I would generally try to avoid this approach myself.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.