I want to use perl
to get the index of
from any given string
and substring
in bash function.
Here is the example for getting the indexOf value from perl script:
https://www.geeksforgeeks.org/perl-index-function/
#!/usr/bin/perl
# String from which Substring
# is to be searched
$string = "Geeks are the best";
# Using index() to search for substring
$index = index ($string, 'the');
# Printing the position of the substring
print "Position of 'the' in the string: $index\n";
Output:
Position of 'the' in the string: 10
Here is the test.sh:
#!/bin/bash
bash_function_get_index_from_perl_script() {
local index="-1"
# Here is the dummy code
# as I don't know how to convert
# the perl script to bash command lines
# and get the result from perl script
index="
#!/usr/bin/perl
# String from which Substring
# is to be searched
$string = "Geeks are the best";
# Using index() to search for substring
$index = index ($string, 'the');
# Printing the position of the substring
print "Position of 'the' in the string: $index\n";
"
printf "%s" "$index"
}
result="$(bash_function_get_index_from_perl_script)"
echo "result is: $result"
Here is the expected output:
result is: 10
How to implement the "bash_function_get_index_from_perl_script
"?
Update:
Here is the bash function for testing:
#!/bin/bash
bash_function_get_index() {
local string="$1"
local search_string="$2"
before=${string%${search_string}*}
index=${#before}
printf "%s" "$index"
}
echo "test 1: $(bash_function_get_index "hello world" "wo")"
echo "test 2: $(bash_function_get_index "hello world" "wox")"
Here is the output:
test 1: 6
test 2: 11
The result of "test 2" is wrong, it should be:
test 2: -1
I want to implement the same "indexOf" function from Java:
https://www.w3schools.com/java/ref_string_indexof.asp
index_of() {
local string="$1"
local search_string="$2"
local fromIndex="$3"
local index=""
# Get the real index here, the result shoule be the same as the Java's "indexOf"
printf "%s" "$index"
}
UPDATE 2:
Here is a testing based on the "@F. Hauri - Give Up GitHub
"'s solution:
The following test_example
is used to get the "inner code
" between "if (feature_is_enabled(Feature_111111)) {
" and "}
".
I used a second variable "hello_world
" to get a from_index
for getting the real index of "}".
But the "test_example
" is not working as expected. It seems the "indexOf()
" function is not working as expected.
#!/bin/bash
indexOf() {
if [[ $1 == -v ]]; then
local -n _iO_result="$2"
shift 2
else
local _iO_result
fi
local _iO_string="$2" _iO_substr="$1" _iO_lhs
_iO_lhs=${_iO_string%"$_iO_substr"*}
_iO_result=${#_iO_lhs}
((_iO_result == ${#_iO_string} )) && _iO_result=-1
case ${_iO_result@A} in _iO_result=* ) echo $_iO_result;;esac
}
indexOf_my_params() {
local string="$1"
local search_string="$2"
local from_index="$3"
local offset=-1
if [[ "$from_index" == "" ]]
then
offset=0
else
if (( $from_index < 0 ))
then
from_index=0
fi
local count=$((${#string} - $from_index))
if (( $count >= 0 ))
then
offset=$from_index
string="${string:from_index:count}"
fi
fi
local index=-1
if [[ "$offset" != "-1" ]]
then
index="$(indexOf "$search_string" "$string")"
if (( $index != -1 ))
then
index=$(($index + $offset))
fi
fi
printf '%s' "$index"
return "$((index < 0))"
}
test_example() {
local content="$(cat <<END
initialize(args, hw);
if (feature_is_enabled(Feature_111111)) {
args.add("foo");
if(1>2) {
args.add("test");
}else{
args.add("x");
}
args.add("hello world");
}
if (feature_is_enabled(Feature_222222)) {
args.add("bar");
}
END
)"
local feature_1_if_begin="if (feature_is_enabled(Feature_111111)) {"
local hello_world="args.add(\"hello world\");"
local feature_1_if_end="}"
local feature_1_if_begin_index="$(indexOf_my_params "$content" "$feature_1_if_begin")"
echo "feature_1_if_begin_index: $feature_1_if_begin_index"
local hello_world_index="$(indexOf_my_params "$content" "$hello_world" "$(($feature_1_if_begin_index + ${#feature_1_if_begin}))")"
echo "hello_world_index: $hello_world_index"
local feature_1_if_end_index="$(indexOf_my_params "$content" "$feature_1_if_end" "$(($hello_world_index + ${#hello_world}))")"
echo "feature_1_if_end_index: $feature_1_if_end_index"
local feature_1_if_block_code="${content:$(($feature_1_if_begin_index + ${#feature_1_if_begin})):$(($feature_1_if_end_index - $feature_1_if_begin_index - ${#feature_1_if_begin}))}"
echo "------ feature_1_if_block_code (inner code) ------"
printf "%s\n" "$feature_1_if_block_code"
}
test_example
exit 0
Here is the actual output (the output is wrong):
feature_1_if_begin_index: 22
hello_world_index: 169
feature_1_if_end_index: 260
------ feature_1_if_block_code (inner code) ------
args.add("foo");
if(1>2) {
args.add("test");
}else{
args.add("x");
}
args.add("hello world");
}
if (feature_is_enabled(Feature_222222)) {
args.add("bar");
Here is the expected output:
------ feature_1_if_block_code (inner code) ------
args.add("foo");
if(1>2) {
args.add("test");
}else{
args.add("x");
}
args.add("hello world");
Why is the "indexOf()
" not working when the search keyword
is "}
"?
UPDATE 3 (use the same "content" for testing as UPDATE 2):
Here is a solution from Paul Hodges but still not working as expected:
Note that I renamed the function name "index
" to "indexof_paul_hodges
".
#!/bin/bash
indexof_paul_hodges ()
{
local string="$1" key="$2" fromIndex=${3:-0};
(( fromIndex )) && string=${string:$fromIndex};
if [[ "$string" =~ "$key" ]]; then
local ndx="${string%%"$key"*}";
echo ${#ndx};
else
echo "-1";
fi
}
test_example() {
local content="$(cat <<END
initialize(args, hw);
if (feature_is_enabled(Feature_111111)) {
args.add("foo");
if(1>2) {
args.add("test");
}else{
args.add("x");
}
args.add("hello world");
}
if (feature_is_enabled(Feature_222222)) {
args.add("bar");
}
END
)"
local feature_1_if_begin="if (feature_is_enabled(Feature_111111)) {"
local hello_world="args.add(\"hello world\");"
local feature_1_if_end="}"
local feature_1_if_begin_index="$(indexof_paul_hodges "$content" "$feature_1_if_begin")"
echo "feature_1_if_begin_index: $feature_1_if_begin_index"
local hello_world_index="$(indexof_paul_hodges "$content" "$hello_world" "$(($feature_1_if_begin_index + ${#feature_1_if_begin}))")"
echo "hello_world_index: $hello_world_index"
local feature_1_if_end_index="$(indexof_paul_hodges "$content" "$feature_1_if_end" "$(($hello_world_index + ${#hello_world}))")"
echo "feature_1_if_end_index: $feature_1_if_end_index"
local feature_1_if_block_code="${content:$(($feature_1_if_begin_index + ${#feature_1_if_begin})):$(($feature_1_if_end_index - $feature_1_if_begin_index - ${#feature_1_if_begin}))}"
echo "------ feature_1_if_block_code (inner code) ------"
printf "%s\n" "$feature_1_if_block_code"
}
test_example
exit 0
Here is the output of "indexof_paul_hodges
" (The result is wrong):
feature_1_if_begin_index: 22
hello_world_index: 106
feature_1_if_end_index: 33
------ feature_1_if_block_code (inner code) ------
args.add("foo");
if(1>2) {
args.add("test");
}else{
args.add("x");
}
args.add("hello world");
}
if (feature_is_enabled(Feature_222
UPDATE 4 (Use the same test_example()
of UPDATE 2
for testing):
Here is a solution from @choroba:
#!/bin/bash
bash_function_get_index() {
local string=$1
local search=$2
[[ $string = *"$search"* ]] || { printf %s -1 ; return ; }
local before=${string%%"$search"*}
local index=${#before}
printf %s "$index"
}
indexOf_my_params() {
local string="$1"
local search_string="$2"
local from_index="$3"
local offset=-1
if [[ "$from_index" == "" ]]
then
offset=0
else
if (( $from_index < 0 ))
then
from_index=0
fi
local count=$((${#string} - $from_index))
if (( $count >= 0 ))
then
offset=$from_index
string="${string:from_index:count}"
fi
fi
local index=-1
if [[ "$offset" != "-1" ]]
then
index="$(bash_function_get_index "$string" "$search_string")"
if (( $index != -1 ))
then
index=$(($index + $offset))
fi
fi
printf '%s' "$index"
return "$((index < 0))"
}
Here is the output of UPDATE 4 (The result is correct)
feature_1_if_begin_index: 22
hello_world_index: 169
feature_1_if_end_index: 194
------ feature_1_if_block_code (inner code) ------
args.add("foo");
if(1>2) {
args.add("test");
}else{
args.add("x");
}
args.add("hello world");
There are many ways. For example, you can send the script to the standard input of perl:
#!/bin/bash
bash_function_get_index_from_perl_script() {
index=$(perl <<- '_PERL_'
$string = 'Geeks are the best';
$index = index $string, 'the';
print "Position of 'the' in the string: $index\n";
_PERL_
)
printf "%s" "$index"
}
result=$(bash_function_get_index_from_perl_script)
echo "result is: $result"
But you don't need Perl for that, you can find the position using parameter expansion in bash itself:
#!/bin/bash
bash_function_get_index() {
string=$1
search=$2
[[ $string = *"$search"* ]] || { printf %s -1 ; return ; }
before=${string%%"$search"*}
index=${#before}
printf %s "$index"
}
for s in the thex ; do
result=$(bash_function_get_index 'Geeks are the best' "$s")
echo "Position of '$s' in the string: $result"
done
To include a start position, just remove everything before the start position from the string before trying to match the substring. Don't forget to add the start position to the result:
bash_function_get_index() {
string=$1
search=$2
pos=${3:-0}
string=${string:$pos}
[[ $string = *"$search"* ]] || { printf %s -1 ; return ; }
before=${string%%"$search"*}
index=${#before}
printf %s $(( pos + index ))
}