0

I have fetched all the directory tags from a file. Now, I am stuck in a situation where I want to store that whole individual directory tags in to different variables as shown below. Thanking in advance.

Below is what I have fetched:

<Directory />
    AllowOverride none
    Order deny, allow
    Deny from all
</Directory>
<Directory "/var/www">
    AllowOverride None
    Require all granted
</Directory>

Required:

# echo $var1
<Directory /> 
AllowOverride none 
Order deny, allow 
Deny from all 
</Directory>

# echo $var2
<Directory "/var/www"> 
AllowOverride None  
Require all granted 
</Directory>

Please note: There are not just 2 directory tags, there are many directory tags without any gap in between them. Every whole individual directory must be stored in a separate variable.

Thanking in advance

14
  • Note your first Directory tag is a self closing element. Did you mean <Directory "/">? Commented Apr 6, 2020 at 11:26
  • Note in the required part you have a quoting problem. If bash variables then var1='some stuff "and some quoted stuff" and more stuff' Commented Apr 6, 2020 at 11:30
  • This may be relevant stackoverflow.com/q/41001475/537980 or this unix.stackexchange.com/q/6389/4778 Commented Apr 6, 2020 at 11:34
  • 2
    This is completely different to what you were asking for before. You now want var1=""" with three quotes and a multi line string? What are the three quotes for? Is this not supposed to go into shell variables? Are you using python instead?
    – terdon
    Commented Apr 7, 2020 at 9:08
  • @terdon I am using bash shell only, using of perl will also help as we have perl in our system. The 3 quotes is to indicate that if it comes as it is then it would be great. Even if it comes in a single line, it will be okay. Commented Apr 7, 2020 at 9:42

2 Answers 2

1

You can iterate over the lines of the file and add the new lines to a string until you encounter a </Directory> tag.

If you only have Directory tags, the code would be much simpler. You'll need to declare varX variables as you go using declare if you do not know how many tags you have.

STR=""
i=1
DIRTAG=false
while read -r LINE; do
    if grep -q '^<Directory' <<< $LINE; then
        DIRTAG=true
    fi
    if $DIRTAG; then
        STR+="$LINE
"
    fi
    if grep -q '^</Directory>' <<< $LINE; then 
        declare var$i="\"\"\"$STR\"\"\"" #You're not clear on the quotes
        STR=""   
        i=$((i+1))
        DIRTAG=false
    fi
done < t.txt

Now echo "$var1"; echo "$var2" outputs the following (do not forget the double quotes. Otherwise newlines will be spaces in the printed output)

"""<Directory />
AllowOverride none
Order deny, allow
Deny from all
</Directory>
"""
"""<Directory "/var/www">
AllowOverride None
Require all granted
</Directory>
"""

When you do not know the number of tags, you can use this to iterate over the created variables

for j in `seq 1 $((i-1))`; do
    var=var$j
    echo "${!var}"
done
1
  • It worked. Thank you for your support. Commented Apr 7, 2020 at 11:21
1

You could process the file to convert it to a list of variable definitions and then source that. For example, you could add an empty line after each closing </Directory> tag, and then use perl's paragraph mode to read each entry as a single line:

$ sed 's|</Directory>|</Directory>\n|' file | 
    perl -000 -lne 'print "var" . ++$k . "=\"$_\"";' 
var1="<Directory />
    AllowOverride none
    Order deny, allow
    Deny from all
</Directory>"

var2="<Directory "/var/www">
    AllowOverride None
    Require all granted
</Directory>"

And you could source that directly to actually set the variables in your current shell:

$ . <(sed 's|</Directory>|</Directory>\n|' file | 
    perl -000 -lne 'print "var" . ++$k . "=\"$_\"";' file )

$ echo "$var1"
<Directory />
    AllowOverride none
    Order deny, allow
    Deny from all
</Directory>

$ echo "$var2"
<Directory /var/www>
    AllowOverride None
    Require all granted
</Directory>

Explanation

  • sed s|</Directory>|</Directory>\n|' file: add a newline after each closing </Directory> tag.
  • -000 : this turns on perl's "paragraph mode" where a "line" is defined by two consecutive newline characters, basically a blank line. So instead of real lines, each "line" is now a paragraph. This lets us treat everything between the opening and closing < Directory /> as a single line since each entry is separated by a blank line.
  • -lne: The -l removes trailing newlines and adds a \n to each print. The -n reads the input file line by line (see above for what "line" means in this context) and applies the script given by -e to each line.
  • print "var" . ++$k . "=\"$_\"": print the desired output format: the string var followed by a number which is incremented for each processed line (++$k), then =\" (the " needs to be escaped as \" since we are within a double-quoted string) and the current "line" ($_ ) followed by the closing ".
  • . <(perl ...): the . is the source command, it will read the fle you give it and run its contents in the current session. The <() is called process substitution, essentially it allows us to treat the output of a command as though it were a file. Note that not all shells support this, so if yours doesn't, you might have to save the output into a file and then source that file.
6
  • I'd suggest that if using perl, use the Config::General module to parse an apache config file Commented Apr 6, 2020 at 14:00
  • @glennjackman would that help getting the values into shell variables as requested by the OP? I've never used it, myself.
    – terdon
    Commented Apr 6, 2020 at 14:02
  • I'd post an example, but Config::General is not happy with the extra whitespace inside the angle brackets Commented Apr 6, 2020 at 14:12
  • @terdon thanks for the help, but what if there is no gap between two directory tags. I am currently having 5 directory tags one after the another without any blank line separating them. Commented Apr 7, 2020 at 7:24
  • 1
    @TahaTikiwala then you should have shown that in your question. I can't guess what your file looks like. Please edit your question and give an example that accurately represents your file so we don't waste your time, or ours, giving solutions that don't help.
    – terdon
    Commented Apr 7, 2020 at 8:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .