my final goal iterate in clean way on parameters used in last command line in bash, in order find path directory. example of wish:
$ cp some_file.txt /some/existing/folder; touch a_new_file.txt $ my_find_func found "/some/existing/folder" in last command. my problem splitting last command in right way, in order handle possible cases. i'm using this:
function myfunc() { last_com="$(history|tail -n2|head -n1|sed -n 's/^\s*[0-9]*\s*//p')" eval "args=( $last_com )" # note: don't care security issue eval can cause arg in "${args[@]}"; echo "$arg" done } i simplicity of using eval in way because handles automatically quoted parameters, escaped spaces, glob expansion, etc... don't have handle myself complicated awk or sed command.
it works fine single commands, this:
/afac/soq $ cd .. /afac $ myfunc cd .. /afac $ touch "some file.txt" /afac $ myfunc touch file.txt but (because of ';' inside array definition), fails when use multiple commands in single line:
$ touch a_file; rm a_file $ myfunc bash: syntax error near unexpected token ';' $ touch a_file && rm a_file $ myfunc bash: syntax error near unexpected token '&&' so make work, have split command string parts when ;, && or || encountered, without forgetting case when these tokens escaped or quoted, saying goodbye simplicity... don't know if i'm able yet parse in way, current knowledge have sed , awk...
what clean (and easiest) solution parameters of command array, handling possibility of quoted parameters, escaped characters, and multiple commands on single-line?
it's maybe quite duplicate, didn't find real solution anywhere.
right able produce this:
#!/bin/bash last_cmd='echo 1 2 "3 4" & && echo "a b" c || echo d "e f" & ' # convert of: &, && or || semicolon cmd=$(sed -e 's/&\?[ ]*&&/;/g' -e 's/&\?[ ]*||/;/g' -e 's/&[ ]*$//' <<< "$last_cmd") # todo: rid of/convert other symbols creating issues eval echo "processed cmd: $cmd" # split command string using semicolon delimiter ifs=';' cmd_arr=($cmd) ifs=' ' args=() onecmd in "${cmd_arr[@]}"; eval "args+=($onecmd)" done arg in "${args[@]}"; echo "$arg" done version 2
last_cmd='echo 1 2 "3 4" && echo "a b" c || echo d ["e f"] $!%#^* ' # remove special characters not having chance appear in pathname cmd=$(sed 's/[][|*^#+&$!%]//g' <<< "$last_cmd") echo "processed cmd: $cmd" ifs=' ' eval "args=($cmd)" arg in "${args[@]}"; echo "$arg" done
Comments
Post a Comment