diff options
author | André Aparício <aparicio99@gmail.com> | 2012-07-21 02:52:35 +0100 |
---|---|---|
committer | Petteri Räty <petsku@petteriraty.eu> | 2012-08-19 17:52:07 +0300 |
commit | b2f509d72462bbf3dcd89d0164e435556980e3ba (patch) | |
tree | d1c06a11be6b391cada86c2251ab26d3cdfc4d5d | |
parent | Merge remote-tracking branch 'aparicio/multiline_string_declaration' (diff) | |
download | libbash-b2f509d72462bbf3dcd89d0164e435556980e3ba.tar.gz libbash-b2f509d72462bbf3dcd89d0164e435556980e3ba.tar.bz2 libbash-b2f509d72462bbf3dcd89d0164e435556980e3ba.zip |
Walker: Support string operations on arrays
When a variable expansion applies some string operation like replace on
the whole array, apply the operation to every element in the array.
-rw-r--r-- | bashast/libbashWalker.g | 83 | ||||
-rw-r--r-- | scripts/var_expansion.bash | 11 | ||||
-rw-r--r-- | src/core/interpreter.cpp | 10 | ||||
-rw-r--r-- | src/core/interpreter.h | 9 |
4 files changed, 77 insertions, 36 deletions
diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g index 460ed0c..768129f 100644 --- a/bashast/libbashWalker.g +++ b/bashast/libbashWalker.g @@ -188,6 +188,14 @@ options walker->set_input_stream(_in); } }; + + std::string replace_expansion(const std::string name, int index, std::function<void(std::string&)> replacer) + { + if(index > -1) + return walker->do_replace_expansion(name, replacer, index); + else + return walker->do_array_replace_expansion(name, replacer); + } } } @@ -582,48 +590,53 @@ var_expansion returns[std::string libbash_value] libbash_value = boost::lexical_cast<std::string>(walker->get_array_length(libbash_name)); } )) - |^(REPLACE_ALL var_name bash_pattern[replace_pattern, true] (libbash_word=raw_string)?) { - libbash_value = walker->do_replace_expansion($var_name.libbash_value, - std::bind(&interpreter::replace_all, - std::placeholders::_1, - replace_pattern, - libbash_word), - $var_name.index); - } - |^(REPLACE_AT_END var_name bash_pattern[replace_pattern, true] (libbash_word=raw_string)?) { + |^(REPLACE_ALL var_or_array_name bash_pattern[replace_pattern, true] (libbash_word=raw_string)?) { + libbash_value = replace_expansion($var_or_array_name.libbash_value, $var_or_array_name.index, + std::bind(&interpreter::replace_all, + std::placeholders::_1, + replace_pattern, + libbash_word)); + } + |^(REPLACE_AT_END var_or_array_name bash_pattern[replace_pattern, true] (libbash_word=raw_string)?) { replace_pattern = sregex(replace_pattern >> eos); - libbash_value = walker->do_replace_expansion($var_name.libbash_value, - std::bind(&interpreter::replace_all, - std::placeholders::_1, - replace_pattern, - libbash_word), - $var_name.index); + libbash_value = replace_expansion($var_or_array_name.libbash_value, $var_or_array_name.index, + std::bind(&interpreter::replace_all, + std::placeholders::_1, + replace_pattern, + libbash_word)); } - |^(LAZY_REMOVE_AT_END var_name bash_pattern[replace_pattern, false] (libbash_word=raw_string)?) { + |^(LAZY_REMOVE_AT_END var_or_array_name bash_pattern[replace_pattern, false] (libbash_word=raw_string)?) { replace_pattern = sregex(bos >> (s1=*_) >> replace_pattern >> eos); - libbash_value = walker->do_replace_expansion($var_name.libbash_value, - std::bind(&interpreter::lazy_remove_at_end, - std::placeholders::_1, - replace_pattern), - $var_name.index); + libbash_value = replace_expansion($var_or_array_name.libbash_value, $var_or_array_name.index, + std::bind(&interpreter::lazy_remove_at_end, + std::placeholders::_1, + replace_pattern)); } |^((REPLACE_AT_START { greedy = true; }|LAZY_REMOVE_AT_START { greedy = false; }) - var_name bash_pattern[replace_pattern, greedy] (libbash_word=raw_string)?) { + var_or_array_name bash_pattern[replace_pattern, greedy] (libbash_word=raw_string)?) { replace_pattern = sregex(bos >> replace_pattern); - libbash_value = walker->do_replace_expansion($var_name.libbash_value, - std::bind(&interpreter::replace_all, - std::placeholders::_1, - replace_pattern, - libbash_word), - $var_name.index); + libbash_value = replace_expansion($var_or_array_name.libbash_value, $var_or_array_name.index, + std::bind(&interpreter::replace_all, + std::placeholders::_1, + replace_pattern, + libbash_word)); + } + |^(REPLACE_FIRST var_or_array_name bash_pattern[replace_pattern, true] (libbash_word=raw_string)?) { + libbash_value = replace_expansion($var_or_array_name.libbash_value, $var_or_array_name.index, + std::bind(&interpreter::replace_first, + std::placeholders::_1, + replace_pattern, + libbash_word)); + }; + +var_or_array_name returns[std::string libbash_value, int index] + :libbash_string=array_name { + $libbash_value = libbash_string; + $index = -1; } - |^(REPLACE_FIRST var_name bash_pattern[replace_pattern, true] (libbash_word=raw_string)?) { - libbash_value = walker->do_replace_expansion($var_name.libbash_value, - std::bind(&interpreter::replace_first, - std::placeholders::_1, - replace_pattern, - libbash_word), - $var_name.index); + |var_name { + $libbash_value = $var_name.libbash_value; + $index = $var_name.index; }; word returns[std::string libbash_value] diff --git a/scripts/var_expansion.bash b/scripts/var_expansion.bash index 97e9587..9ba4286 100644 --- a/scripts/var_expansion.bash +++ b/scripts/var_expansion.bash @@ -79,6 +79,17 @@ echo ${FOO039/*(l)} echo ${FOO039/?(l)} echo ${FOO039/@([a-c]|[k-m])} echo ${FOO039//@([a-c]|[k-m])} +FOO40=("foo bar" foo bar foobar) +FOO40=("foo bar foo" bar foo foobar) +echo ${FOO40[@]/foo/poo} +echo ${FOO40[@]//foo/poo} +echo ${FOO40[@]#foo} +echo ${FOO40[@]##f*o} +echo ${FOO40[@]%foo} +echo ${FOO40[@]%%f*o} +echo ${FOO40[@]/#foo} +echo ${FOO40[@]/%foo} +echo ${FOO40[@]} target="abc123abc" echo "${target##+(ab[c])*([[:digit:]])}" function positional_parameter_test(){ diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp index 1b8ef0a..274d01d 100644 --- a/src/core/interpreter.cpp +++ b/src/core/interpreter.cpp @@ -244,6 +244,16 @@ std::string interpreter::do_replace_expansion(const std::string& name, return value; } +std::string interpreter::do_array_replace_expansion(const std::string& name, + std::function<void(std::string&)> replacer) const +{ + std::vector<std::string> array; + resolve_array<std::string>(name, array); + for(auto i = array.begin(); i != array.end(); ++i) + replacer(*i); + return boost::algorithm::join(array, resolve<std::string>("IFS").substr(0, 1)); +} + std::string::size_type interpreter::get_length(const std::string& name, const unsigned index) const { diff --git a/src/core/interpreter.h b/src/core/interpreter.h index 3c6dde6..0feadef 100644 --- a/src/core/interpreter.h +++ b/src/core/interpreter.h @@ -514,7 +514,7 @@ public: int length) const; /// \brief perform replacement expansion - /// \param name the name of the varaible that needs to be expanded + /// \param name the name of the variable that needs to be expanded /// \param replacer the function object used to perform expansion /// \param index array index, use index=0 if it's not an array /// \return the expanded value @@ -522,6 +522,13 @@ public: std::function<void(std::string&)> replacer, const unsigned index) const; + /// \brief perform array replacement expansion + /// \param name the name of the array that needs to be expanded + /// \param replacer the function object used to perform expansion + /// \return the expanded value + std::string do_array_replace_expansion(const std::string& name, + std::function<void(std::string&)> replacer) const; + /// \brief get the length of a string variable /// \param name the name of the variable /// \param index the index of the variable |