Samir Boulil
Samir Boulil

Reputation: 93

Substitution with sed + bash function

my question seems to be general, but i can't find any answers.

In sed command, how can you replace the substitution pattern by a value returned by a simple bash function.

For instance, I created the following function :

function parseDates(){
    #Some process here with $1 (the pattern found)
    return "dateParsed;
}

and the folowing sed command :

myCatFile=`sed -e "s/[0-3][0-9]\/[0-1][0-9]\/[0-9][0-9]/& parseDates &\}/p" myfile`

I found that the caracter '&' represents the current pattern found, i'd like it to be passed to my bash function and the whole pattern to be substituted by the pattern found +dateParsed.

Does anybody have an idea ? Thanks

Upvotes: 9

Views: 14899

Answers (7)

Roger
Roger

Reputation: 8576

Bash function inside sed (maybe for other purposes):

multi_stdin(){ #Makes function accepet variable or stdin (via pipe)
    [[ -n "$1" ]] && echo "$*" || cat -
}

sans_accent(){ 
    multi_stdin "$@" | sed '
        y/àáâãäåèéêëìíîïòóôõöùúûü/aaaaaaeeeeiiiiooooouuuu/
        y/ÀÁÂÃÄÅÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜ/AAAAAAEEEEIIIIOOOOOUUUU/
        y/çÇñÑߢÐð£Øø§µÝý¥¹²³ªº/cCnNBcDdLOoSuYyY123ao/
    '
}

eval $(echo "Rogério Madureira" | sed -n 's#.*#echo & | sans_accent#p')

or

eval $(echo "Rogério Madureira" | sed -n 's#.*#sans_accent &#p')

Rogerio

And if you need to keep the output into a variable:

VAR=$( eval $(echo "Rogério Madureira" | sed -n 's#.*#echo & | desacentua#p') )
echo "$VAR"

Upvotes: 1

Antonio
Antonio

Reputation: 11

Agree with Glenn Jackman. If you want to use bash function in sed, something like this :

sed -rn 's/^([[:digit:].]+)/`date -d @&`/p' file |
while read -r line; do
    eval echo "$line"
done

My file here begins with a unix timestamp (e.g. 1362407133.936).

Upvotes: 1

xiaofengmanlou
xiaofengmanlou

Reputation: 51

you can use the "e" option in sed command like this:

cat t.sh

myecho() {
        echo ">>hello,$1<<"
}
export -f myecho
sed -e "s/.*/myecho &/e" <<END
ni
END

you can see the result without "e":

cat t.sh

myecho() {
        echo ">>hello,$1<<"
}
export -f myecho
sed -e "s/.*/myecho &/" <<END
ni
END

Upvotes: 4

user unknown
user unknown

Reputation: 36229

You can glue together a sed-command by ending a single-quoted section, and reopening it again.

sed -n 's|[0-3][0-9]/[0-1][0-9]/[0-9][0-9]|& '$(parseDates)' &|p' datefile

However, in contrast to other examples, a function in bash can't return strings, only put them out:

function parseDates(){
    # Some process here with $1 (the pattern found)
    echo dateParsed
}

Upvotes: -4

glenn jackman
glenn jackman

Reputation: 246827

sed -e 's#[0-3][0-9]/[0-1][0-9]/[0-9][0-9]#& $(parseDates &)#' myfile |
while read -r line; do
    eval echo "$line"
done

Upvotes: 0

drysdam
drysdam

Reputation: 8637

I'd like to know if there's a way to do this too. However, for this particular problem you don't need it. If you surround the different components of the date with ()s, you can back reference them with \1 \2 etc and reformat however you want.

For instance, let's reverse 03/04/1973:

echo 03/04/1973 | sed -e 's/\([0-9][0-9]\)\/\([0-9][0-9]\)\/\([0-9][0-9][0-9][0-9]\)/\3\/\2\/\1/g'

Upvotes: 1

ghostdog74
ghostdog74

Reputation: 342373

do it step by step. (also you could use an alternate delimiter , such as "|" instead of "/"

function parseDates(){
    #Some process here with $1 (the pattern found)
    return "dateParsed;
}

value=$(parseDates)
sed -n "s|[0-3][0-9]/[0-1][0-9]/[0-9][0-9]|& $value &|p" myfile

Note the use of double quotes instead of single quotes, so that $value can be interpolated

Upvotes: 0

Related Questions