I am trying to make a recursive awk. The goal is to be able to ask for 4 and get 4 5 6 7
The testfile.csv looks like this:
From,To
2,3
1,2
4,5
3,4
5,6
6,7
0,1
My awk code works if I leave out the recursive part, but when I run this:
#!/bin/bash
path()
{
if [ -z "$1" ]; then
echo " _"
else
last= $(path $(awk -v myvar="$1" -F"," '$1 ~ myvar { print $2 }' testfile.csv))
echo $(( last ))
fi
}
path $1
All I get is:
$ bash path 4
path: line 8: awk -v myvar=4 -F, '4 ~ myvar { print }' testfile.csv: syntax error in expression (error token is "myvar=4 -F, '4 ~ myvar { print }' testfile.csv")
0
I've read all I can find on the subject. I can do the awk or the recursion, but I can't get them to work together.
Any ideas? Thank you
CodePudding user response:
An efficient, robust, portable way to do what you want would be:
path() {
awk -v cur="$1" '
BEGIN { FS="," }
{ map[$1] = $2 }
END {
out = cur
while ( cur in map ) {
nxt = map[cur]
out = out OFS nxt
delete map[cur]
cur = nxt
}
print out
}
' testfile.csv
}
path 4
4 5 6 7
That would be orders of magnitude faster than using a recursive shell function. The delete map[cur]
is to protect against infinite recursion in your data, e.g. 4,5
and 5,4
.
CodePudding user response:
To complement what Ed wrote, here is a pure bash implementation:
#!/usr/bin/env bash
declare -a map=()
while IFS=, read -r k v; do
map[k]=$v
done
ppat () {
cur=$1
local -a out=("$cur")
while [[ -v map["$cur"] ]]; do
nxt=${map[$cur]}
out =("$nxt")
unset map["$cur"]
cur=$nxt
done
printf '%s\n' "${out[*]}"
}
ppat "$1"
Usage example:
$ bash script.sh 4 < testfile.csv
4 5 6 7