string handling in bash - bash

the problem I met is like this:
given a string dimensioning-inspection_depth-0rules_20120306-084158
I'd like to get the first part of the string: dimensioning-inspection_depth-0rules, so to speak, get rid of the time stamp part. In perl, it's like a piece of work to do the job using regular expression. But since I'm new to bash, I'd like to know
the best-practice way of doing it in Bash.

If you don't want to pipe the string to sed, you can use Bash variable mangling:
$ string=dimensioning-inspection_depth-0rules_20120306-084158
$ echo ${string%_*}
dimensioning-inspection_depth-0rules
More information on variable mangling here.

You can do this:
str=dimensioning-inspection_depth-0rules_20120306-084158
echo ${str%_*}
This will remove anything after and including the last _ in the string, so if your string always has the form something_date-time, you will always be left with something part.
More info here:
http://tldp.org/LDP/abs/html/string-manipulation.html

a="dimensioning-inspection_depth-0rules_20120306-084158"
echo $a | head -c -16
So as the timestamp will always be equal width (16 characters that you are trying to trim off the end in this case), head -c -16 should work for you

Related

Grep variable at exact point in string

I have a file with numerical data, and reading the variables from another file extract the correct string.
I have my code to read in the variables.
The problem is the variable can occur at different points within the string, i only want the string that has the variable on the right-hand side, i.e. the last 8 characters.
e.g.
grep 0335439 foobar.txt
00032394850033543984
00043245845003354390
00060224460033543907
00047444423700335439
In this case its the last line.
I have tried to write something using ${str: -8}, but then I lose the data in front.
I have found this command
grep -Eo '^.{12}(0335439)' foobar.txt
This works, however when I use my script and put a variable in the place it doesn't, grep -Eo '^.{12}($string)' foobar.txt.
I have tried without brackets but it still does not work.
Update:
In this case the length of the string is always 20 characters, so counting from the LHS is OK in my case, but you are correct its was not the answer to the original question. I tried to comment the code so say this but pasting it into the comment box removed the formatting.
i only want the string that has the variable on the right-hand side, i.e. the last 8 characters
A non-regex approach using awk is better suited for this job:
s='00335439'
awk -v n=8 -v kw="$s" 'substr($0, length()-n, n) == kw' file
00043245845003354390
Here we passing n=8 to awk and using substr($0, length()-n, n) we are getting last n characters in a line, which is then compared against variable kw which is set to a value on command line.

Combine two expression in Bash

I did check the ABS, but it was hard to find a reference to my problem/question there.
Here it is. Consider the following code (Which extracts the first character of OtherVar and then converts MyVar to uppercase):
OtherVar=foobar
MyChar=${OtherVar:0:1} # get first character of OtherVar string variable
MyChar=${MyChar^} # first character to upper case
Could I somehow condense the second and third line into one statement?
P.S.: As was pointed out below, not needs to have a named variable. I should add, I would like to not add any sub-shells or so and would also accept a somehow hacky way to achieve the desired result.
P.P.S.: The question is purely educational.
You could do it all-in-one without forking sub-shell or running external command:
printf -v MyChar %1s "${OtherVar^}"
Or:
read -n1 MyChar <<<"${OtherVar^}"
Another option:
declare -u MyChar=${OtherVar:0:1}
But I can't see the point in such optimization in a bash script.
There are more suitable text processing interpreters, like awk, sed, even perl or python if performance matters.
You could use the cut command and put it in a complex expression to get it on one line, but I'm not sure it makes the code too much clearer:
OtherVar=foobar
MyChar=$(echo ${OtherVar^} | cut -c1-1) # uppercase first character and cut string

How to convert a variable to string format? KSH shell scripting

I am trying to convert a variable to a string format so I can use java runsql utility to insert its value into a database later. The database needs the value to be in a char format, hence string.
This is a dumbed down version of my code so I can get to the heart of what I'm asking -
#!/bin/ksh -x
value1=2018-01-01
value2=2018-02-01
mystring=$value1,$value2
echo $mystring
stringify=${'value1'},${'value2'})
echo $stringify
What happens is I get no output for stringify or depending on how I switch up the arrangement of the symbols I get the literal string 'value1' or 'value2'.
What am I doing wrong? I feel like this is very simple, maybe I've just been staring at it too long, I dunno.
You can just escape quote like this:
mystring=\'$value1\',\'$value2\'
Output:
$ echo $mystring
'2018-01-01','2018-02-01'
A simpler option to get the same output (as suggested by #CharlesDuffy) is:
mystring="'$value1','$value2'"
You can just do like this, more simpler:
#!/bin/ksh -x
value1=2018-01-01
value2=2018-02-01
mystring=$value1,$value2
echo $mystring
stringify="'$value1','$value2'" #use double-quotes around the variables
echo $stringify
Output:
2018-01-01,2018-02-01
'2018-01-01','2018-02-01'

Variable not getting assigned in bash after a curl hit

I have a shell script where I have a statement:
isPartial = $searchCurl| grep -Po '\"partialSearch\":(true|false)'|sed 's/\\\"partialSearch\\\"://'
now, if I just echo the RHS
$searchCurl| grep -Po '\"partialSearch\":(true|false)'|sed 's/\\\"partialSearch\\\"://'
it prints "partialSearch":true, but the variable isPartial doesn't get initialized .
Why is this happening and how can I fix it ?
Since the number of backslashes in your examples varies, it is not clear to me if the double quotes are already escaped in the input text. I’ll assume they are not, i.e. the input text looks something like:
sometext... "partialSearch":true ... sometext...
..bla bla bla... "partialsearch":false ...
and my examples below will work under this assumption.
There are a number of points to be made.
You seem to be trying to parse JSON input with regular expressions. While this could be acceptable for quick-and-dirty one-time jobs where you know the exact format of the data being processed, in general it is a very bad idea. You should use a JSON parser like jq.
You obviously have stored some bash code in the variable searchCurl. This is considered bad practice. Instead of searchCurl="... code ..." you should do function searchCurl () { ... code ... } and call searchCurl without prefixing it with a dollar sign. Variables are for values, functions are for code.
In most cases, if you are going to use sed, it’s better to use it for everything without invoking grep. Sometimes it can be simpler to have both. See below for an example.
To assign the output of a command to a variable, you have to use command substitution.
In short, if in your input text you have only one match of '"partialSearch":(true|false)', this is what you want:
isPartial=$(searchCurl|sed -rn 's/^.*"partialSearch":(true|false).*$/\1/p')
If you have more and the input text is one big line as I suppose, usage of grep -o might simplify the task of splitting the input into one match per line, so that
isPartial=$(searchCurl|grep -Po '"partialSearch":(true|false)'|sed -e 's/^.*://')
might be what you want (and in this case, isPartial will hold a space-separated list of true and false).

Search and replace in Shell

I am writing a shell (bash) script and I'm trying to figure out an easy way to accomplish a simple task.
I have some string in a variable.
I don't know if this is relevant, but it can contain spaces, newlines, because actually this string is the content of a whole text file.
I want to replace the last occurence of a certain substring with something else.
Perhaps I could use a regexp for that, but there are two moments that confuse me:
I need to match from the end, not from the start
the substring that I want to scan for is fixed, not variable.
for truncating at the start: ${var#pattern}
truncating at the end ${var%pattern}
${var/pattern/repl} for general replacement
the patterns are 'filename' style expansion, and the last one can be prefixed with # or % to match only at the start or end (respectively)
it's all in the (long) bash manpage. check the "Parameter Expansion" chapter.
amn expression like this
s/match string here$/new string/
should do the trick - s is for sustitute, / break up the command, and the $ is the end of line marker. You can try this in vi to see if it does what you need.
I would look up the man pages for awk or sed.
Javier's answer is shell specific and won't work in all shells.
The sed answers that MrTelly and epochwolf alluded to are incomplete and should look something like this:
MyString="stuff ttto be edittted"
NewString=`echo $MyString | sed -e 's/\(.*\)ttt\(.*\)/\1xxx\2/'`
The reason this works without having to use the $ to mark the end is that the first '.*' is greedy and will attempt to gather up as much as possible while allowing the rest of the regular expression to be true.
This sed command should work fine in any shell context used.
Usually when I get stuck with Sed I use this page,
http://sed.sourceforge.net/sed1line.txt

Resources