aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Aparício <aparicio99@gmail.com>2012-07-21 02:52:35 +0100
committerPetteri Räty <petsku@petteriraty.eu>2012-08-19 17:52:07 +0300
commitb2f509d72462bbf3dcd89d0164e435556980e3ba (patch)
treed1c06a11be6b391cada86c2251ab26d3cdfc4d5d
parentMerge remote-tracking branch 'aparicio/multiline_string_declaration' (diff)
downloadlibbash-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.g83
-rw-r--r--scripts/var_expansion.bash11
-rw-r--r--src/core/interpreter.cpp10
-rw-r--r--src/core/interpreter.h9
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