Query value starting with dash causes elasticsearch count api to fail - elasticsearch

This works:
GET /box/item/_count?q=name%3Aabcdef
This doesn't:
GET /box/item/_count?q=name%3A-abcdef
(The difference is the dash)
Reply from elasticsearch is: "Cannot parse 'name:-abcdeft'"
box/item is not_analyzed.
What to do?

Escaping it with a backslash works for me:
GET /box/item/_count?q=name%3A\-abcdef
so does using quotes:
GET /box/item/_count?q=name%3A"-abcdef"
The hyphen is a special character and like others needs to be escaped:
reserved characters
If you need to use any of the characters which function as operators
in your query itself (and not as operators), then you should escape
them with a leading backslash. For instance, to search for (1+1)=2,
you would need to write your query as \(1\+1\)=2.
The reserved characters are: + - && || ! ( ) { } [ ] ^ " ~ * ? : \ /
Failing to escape these special characters correctly could lead to a
syntax error which prevents your query from running.

Related

Why am I getting a leading sing quote in this echo?

I am trying to debug a bash shell script where I am trying to surround a string/variable with single quotes. I am seeing the following results and am stumped on how to debug this. It obviously has something to do with the content of the variable. I thought the variable may be an array hence some of the echo statements. IN_JSON is being constructed via calls to "jq" to construct some JSON.
echo "IN_JSON = ${IN_JSON}"
echo "IN_JSON = ${IN_JSON[*]}"
echo "IN_JSON = '${IN_JSON[*]}'"
echo "IN_JSON = '" ${IN_JSON} "'"
echo "${#IN_JSON[#]}"
Output:
IN_JSON = {"name":"RX-CLAIM-FILLED"}
IN_JSON = {"name":"RX-CLAIM-FILLED"}
'N_JSON = '{"name":"RX-CLAIM-FILLED"}
'_JSON = ' {"name":"RX-CLAIM-FILLED"}
1
What's going on here and how do I troubleshoot this? It obviously has something to do with the contents of IN_JSON, but I'm not sure why or what is going on here.
The expansion of ${IN_JSON[*]} contains a carriage return character that resets the position of the cursor to beginning of the line, so that the next character ' is printed on beginning of the line.
Most probably, you want to run your file via dos2unix.

bash script - unable to set variable with double quotes in value

Need help in fixing this bash script to set a variable with a value including double quotes. Somehow I am defining this incorrectly as my values foo and bar are not enclosed in double quotes as needed.
My script thus far:
#!/usr/local/bin/bash
set -e
set -x
host='127.0.0.1'
db='mydev'
_account="foo"
_profile="bar"
_version=$1
_mongo=$(which mongo);
exp="db.profile_versions_20170420.find({account:${_account}, profile:${_profile}, version:${_version}}).pretty();";
${_mongo} ${host}/${db} --eval "$exp"
set +x
Output shows:
+ host=127.0.0.1
+ db=mydev
+ _account=foo
+ _profile=bar
+ _version=201704112004
++ which mongo
+ _mongo=/usr/local/bin/mongo
+ exp='db.profile_versions_20170420.find({account:foo, profile:bar, version:201704112004}).pretty();'
+ /usr/local/bin/mongo 127.0.0.1/mydev --eval 'db.profile_versions_20170420.find({account:foo, profile:bar, version:201704112004}).pretty();'
MongoDB shell version: 3.2.4
connecting to: 127.0.0.1/mydev
2017-04-22T15:32:55.012-0700 E QUERY [thread1] ReferenceError: foo is not defined :
#(shell eval):1:36
What i need is account:"foo", profile:"bar" to be enclosed in double quotes.
In bash (and other POSIX shells), the following 2 states are equivalent:
_account=foo
_account="foo"
What you want to do is to preserve the quotations, therefore you can do the following:
_account='"foo"'
Since part of what you're doing here is forming JSON, consider using jq -- which will guarantee that it's well-formed, no matter what the values are.
host='127.0.0.1'
db='mydev'
_account="foo"
_profile="bar"
_version=$1
json=$(jq -n --arg account "$_account" --arg profile "$_profile" --arg version "$_version" \
'{$account, $profile, version: $version | tonumber}')
exp="db.profile_versions_20170420.find($json).pretty();"
mongo "${host}/${db}" --eval "$exp"
This makes jq responsible for adding literal quotes where appropriate, and will avoid attempted injection attacks (for instance, via a version passed in $1 containing something like 1, "other_argument": "malicious_value"), by replacing any literal " in a string with \"; a literal newline with \n, etc -- or, with the | tonumber conversion, failing outright with any non-numeric value.
Note that some of the syntax above requires jq 1.5 -- if you have 1.4 or prior, you'll want to write {account: $account, profile: $profile} instead of being able to write {$account, $profile} with the key names inferred from the variable names.
When you need to use double quotes inside a double quoted string, escape them with backslashes:
$ foo="acount:\"foo\"" sh -c 'echo $foo'
acount:"foo"
I needed to enquote something already in a variable and stick that in a variable. Expanding on Robert Seaman's answer, I found this worked:
VAR='"'$1'"'
(single quote, double quote, single quote, variable,single quote, double quote, single quote)

Syntax error at line 1 : `(' is not expected

As I'm new to Unix, can someone help why I get this error?
Error: 0403-057 Syntax error at line 1 : `(' is not expected
Unix server used: AIX servname 1 6 00F635064C00
Script used (to send email alert if day before yesterday source files didn't arrive):
#!/usr/bin/ksh
count=$(sqlplus $PROD_DB #select count(*) from file_audit where (file_name like '%abc%' or file_name like '%dce%') and substr(file_name,17,8)=to_char(to_date(sysdate-2,'DD/MM/YY'), 'yyyymmdd') > asa_file_count.log)
daybefore=`TZ=aaa48 date +%d-%m-%Y`
if [[ $count -lt 20 ]]
then
echo "Alert - Source files are yet to be received for date: $daybefore" | mail -s "Alert : Source data files missing" s#g.com
fi
Parentheses are special to the shell. Your SQL script contains parentheses you don't want the shell to process. However, the shell processes all non-quoted parentheses. Therefore, you can use quotes to prevent the parentheses in your SQL from being interpreted by the shell:
count=$(sqlplus $PROD_DB "#select count(*) from file_audit where (file_name like '%abc%' or file_name like '%dce%') and substr(file_name,17,8)=to_char(to_date(sysdate-2,'DD/MM/YY'), 'yyyymmdd')" > asa_file_count.log)
# ^ and similarly, a closing quote at the end, just before ">asa_file..." .
Now, there is a second issue: you have
count=$(sqlplus ... > asa_file_count.log)
However, I think this means count will always be empty, since the count will go into asa_file_count.log and will not be available to be captured with $(). I believe removing the >asa_file_count.log will probably do what you want:
count=$(sqlplus "$PROD_DB" "<your query>")
(I also put double-quotes around $PROD_DB just in case PROD_DB's value contains any spaces.)

Compare a Bash string literal to a local variable

#!/bin/bash
function getComment(){
local lang=$1;
local theComment=$2;
if [$lang == "Java"] #Surprisingly, an error occurs here: prog.sh: line 6: [Java: command not found
then
echo "//"$theComment; return;
else
echo "Language not found!"; return;
fi
}
getComment "Java" "Whoo!";
exit $?
I'm writing a Bash script that compares a variable to a string literal, and I'm using [$lang == "Java"] (as shown above) to compare the value of lang to "Java". However, this comparison produces the following error:
stderr:
prog.sh: line 6: [Java: command not found
I've tried using [$lang -eq "Java"] and ($lang -eq "Java") as well, but those statements didn't work either, and they produced exactly the same error.
Why is this error occurring, and what is the correct way to compare a local variable to a string literal?
You need spaces around [ and ]:
if [ "$lang" = "Java" ]
[ is a command (it's a synonym for test), and like any other command you delimit the parameters with spaces.
You should also put variables in double quotes, in case the value is empty or contains whitespace or wildcard characters.
Finally, the operator to perform string comparison is =, although some versions of test allow == as an extension.
First, you have to enclose the variable between double quotes, because the variable could have some spaces or special characters.
Finally remember that "[" it's an executable by itself (usually is in /bin).
if [ "$lang" == "Java" ]; then
First thing is, don't use [ ] - it's better to use [[.
And second - you need to add some spaces:
if [[ $lang == Java ]]

Shell script test

I'm tring to update a bash script written by someone else and I've come accross a line I'm not sure about.
Can anyone tell me what the following check does:
if [ :$RESULT != :0,0 ]
I assume it's checking for some value in $RESULT, possibly with a substring?
Any help appreciated!
The command [ is just an alias of the command test, the closing square bracket just being sytax sugar (the command [ ignores the last argument if it's a closing bracket), so the line actually reads
if test :$RESULT != :0,0
It compares if the string :$RESULT equals to the string :0,0. The colon is prepended for the case that the variable $RESULT is empty. The line would look like the following if the colon was omitted and $RESULT was an empty string:
if test != 0,0
This would lead to an error, since test expects an argument before !=. An alternative would be to use quotes to indicate that there is an argument, which is an empty string:
if test "$RESULT" != 0,0
# Will become
if test "" != 0,0
The variation you posted is more portable, though.
I think the : is a common trick people use in case the variable is empty.
If it's empty, then the shell would have this:
if [ != 0,0 ]
which would be a syntax error. Putting the : in front means that if the variable is empty the shell has this:
if [ : != :0,0 ]
which is not a syntax error and would (correctly) report false.
Sometimes you'll see an x used in the way that the colon is used in your example.
The preferred way to do this type of test in Bash is to use the double square bracket:
if [[ $RESULT != 0,0 ]]
The double bracket form allows more flexibility, improved readability, reduced need for escaping and quoting and a few more features. See this page for more information.
If you want to test numeric values, instead of strings or files, use the double parentheses:
if (( 3 + 4 > 6 ))

Resources