I am wanting to grep an SQL file to get the following information, however, I am struggling to get it to work - I've tried the following;
grep -Poe "-- Server version \K.*" _schemas.sql
The line in the SQL dump is
-- MySQL dump 10.13 Distrib 5.1.55, for unknown-linux-gnu (x86_64)
--
-- Host: 10.213.118.88 Database: mysql
-- ------------------------------------------------------
-- Server version 5.1.55
The format will not change - I only want to grep the actual numbers of the server version, so in this case, 5.1
sqlver=(awk '/Server version/ { split($NF,a,"."); print a[1] "." a[2] }' _schemas.sql)
if [ $sqlver -eq 5.1 ];
then
/opt/migrate/db_import.sh: line 118: [: awk: integer expression expected
To strip the leftmost spaces, add "*" before \K
grep -Poe "-- Server version *\K.*" _schemas.sql #5.1.55
To retain only 5.1 in your case, replace \K.* with *\K.{3} (What You Want)
grep -Poe "-- Server version *\K.{3}" _schemas.sql #5.1
Where You are not sure whether it's tabs or spaces, use:
grep -Poe "-- Server version[ \t]*\K.{3}" _schemas.sql #5.1
Corresponding sed Versions:
sed -nE "s/-- Server version *(.*)/\1/p" _schemas.sql #5.1.55
sed -nE "s/-- Server version *(.*)\..*/\1/p" _schemas.sql #5.1
sed -nE "s/-- Server version[ \t]*(.*)\..*/\1/p" _schemas.sql #5.1
One awk idea:
$ awk '/Server version/ { print $NF }' _schemas.sql
5.1.55
If the intent is to display just the first 2 decimal-delimited numbers:
$ awk '/Server version/ { split($NF,a,"."); print a[1] "." a[2] }' _schemas.sql
5.1
The following gives you the first two components of the version.
-- Server version and the version string can be separated by any number of spaces or tabs.
sed -ne "s/^-- Server version[ \t]*\([0-9]\{1,\}\.[0-9]\{1,\}\)\..*$/\1/p" < _schemas.sql
Related
Problem Set (Raspberry Pi OS):
I have a file example.conf that contains a line IPv4addr=XXXXX. I am attempting to change this to the IP that is generated the in the command
ipTest=$(ip --brief a show | grep eth0 | awk '{ print $3 }')
I want to automate this file change during a script install.sh, the line I am attempting is:
IPtest=$(ip --brief a show | grep eth0 | awk '{ print $3 }')
sudo sed -e "/IPv4addr/s/[^=]*$/$IPtest/" example.conf
Returns error:
sed: -e expression #1, char 32: unknown option to `s'
A simple line in that code works, such as SimpleTest='Works'
Any thoughts? I am open to other solutions as well, however I am not an experienced linux user so I am using the tools I know to work with other problem sets.
$IPtest contains the / character; try something like this:
IPtest=$(ip --brief a show | grep eth0 | awk '{ print $3 }')
sudo sed -e '/IPv4addr/s#[^=]*$#'"$IPtest"'#' example.conf
You can shorten your variable and allow awk to do the job of grep at the same time
IPtest=$(ip --brief a s | awk '/eth0/{print $3}')
Using sed grouping and back referencing
sed -i.bak "s|\([^=]*.\).*|\1$IPtest|" example.conf
A file (foo.csv) contain entries (four columns) as follows:
A 5.3 3.2 1.2
A 2.1 3.4 6.7
A 3.4 2.1 5.6
A 0.4 2.2 4.2
In this file, I want to add the total number of lines in the first line followed by an empty line.
I want the output to be as follow.
4
A 5.3 3.2 1.2
A 2.1 3.4 6.7
A 3.4 2.1 5.6
A 0.4 2.2 4.2
Here is what I tried.
#to get the total number of lines in the file foo.csv
t=$((wc -l foo.csv | cut -d" " -f1))
#to add an empty line
sed -i "1i\\" foo.csv
#to insert the total number at the top; this works fine.
sed -i "1i $t" foo.csv
I need to do this for a bunch of files. So, script will be useful. The problem seems to be in sed -i "1i\\" foo.csv. How to correct this?
do the line counting with awk as well.
$ awk 'NR==FNR{next} FNR==1{print NR-1 ORS}1' file{,}
or, with tac...tac
$ tac file | awk '1; END{print ORS NR}' | tac
If you are ok with awk could you please try following.
awk -v line=$(wc -l < Input_file) 'FNR==1{print line ORS} 1' Input_file
In case you want to add output into Input_file itself then append > temp_file && mv temp_file Input_file to above code then.
Explanation: Adding explanation for above code too now.
awk -v line=$(wc -l < Input_file ) ' ##Creating variable line whose value is bash command wc -l to get line count for Input_file as per OP request.
FNR==1{ ##Checking if line number is 1 here then do following.
print line ORS ##Printing variable line here with ORS whose value is new line here.
} ##Closing FNR block here.
1 ##awk works on method of pattern and action mentioning 1 making condition TRUE and no action will make print to happen.
' Input_file ##Mentioning Input_file name here.
You can do it quite simply using sed with the 0,addr2 form (see man sed under "Addresses") with general substitution, e.g.
$ sed '0,/^/s/^/4\n\n/' file
4
A 5.3 3.2 1.2
A 2.1 3.4 6.7
A 3.4 2.1 5.6
A 0.4 2.2 4.2
The sed expression simply finds the first occurrence of the beginning of the line 0,/^/ and then substitutes the beginning of the line with 4\n\n, using s/^/4\n\n/
Add the -i option to edit-in-place (or -i.bak to create a back of the original (e.g. file.bak) while editing in place.
If you are interested in setting the number of lines, then you can simply get the lines with wc -l using command substitution, e.g.
$ sed "0,/^/s/^/$(wc -l <file2)\n\n/" file2
8
A 5.3 3.2 1.2
A 2.1 3.4 6.7
A 3.4 2.1 5.6
A 0.4 2.2 4.2
A 5.3 3.2 1.2
A 2.1 3.4 6.7
A 3.4 2.1 5.6
A 0.4 2.2 4.2
(note: the use of double-quotes instead of single-quotes to allow expansion of the command substitution)
This might work for you (GNU sed):
sed -e '1e wc -l <file' -e '1H;1g' file
or to do everything in sed:
sed -e '1e sed "$=;d" file' -e '1H;1g' file
This uses the e command to evaluate unix commands. Normally this is done using the e flag to the s command, but it can be used following an address, as in this situation.
An alternative, using a pipe:
wc -l <file | sed '1G' - file
or:
sed '$=;d' file | sed '1G' - file
Use the result of a wc or sed command as the first input file.
On retrospect, the easiest solution (although not the most efficient):
sed 'H;$!d;=;x' file
Which slurps the file into the hold space and inserts the number of lines and a blank line before printing out the hold space.
Friends,
I'm trying to extract the last part of following path in a ksh script:
TOOL_HOME=/export/fapps/mytool/mytool-V2-3-4
I want to extract the version # (i.e., 2-3-4) from the above.
awk runs fine on SuSE:
echo $TOOL_HOME | awk -F'mytool-V' '{print $2}'
#2-3-4
However, on Solaris 10, it produces the following:
#ytool
So on Solaris, awk is ignoring everything after the first character in -F'mytool-V'
What should i do to get the same output on both OS's?
On Solaris use /usr/xpg4/bin/awk, not /bin/awk (aka "old, broken awk").
Solaris awk is broken...
$ echo "$TOOL_HOME" | awk '{sub(/.*mytool-V/,"")}1'
2-3-4
or simply with sed
$ echo "$TOOL_HOME" | sed 's/.*mytool-V//'
2-3-4
No need to use awk or any other external program. ksh can do that:
echo ${TOOL_HOME##*mytool-V}
dokku ls shows the following but how can I get the status of app-1470418443 using awk for example ?
So that magic command returns running.
-----> App Name Container Type Container Id Status
app-1470418443 web 78a092d176f1 running
example web 3b7803c49e04 running
example2 web a750f2b4be44 running
awk '$1=="app-1470418443"{print $NF}'
Since there is trailing space in the example output you have to get all non-space characters ([^ ]*) and then all the space (_*, underscore _ represents space as space didn't render at all) in the end of the string ($) and print only the matching parts (grep -o):
$ grep "^app-1470418443 " file | grep -o "[^ ]* *$"
running
Without trailing space, the latter grep would simplify a bit (well 2 bytes) to match only the non-space chars:
$ grep "^app-1470418443 " file | grep -o "[^ ]*$"
running
Trying to find a single word and replace it with the contents of a file. Works on MacOS, but not under linux.
Here is the awk that fails under linux:
awk -v var="${blah}" '{sub(/%WORD%/,var)}1' file.xml
(file.xml is 122 lines, 4.7K)
Error is:
awk: program limit exceeded: replacement pieces size=255
Same file.xml under MacOS, using a slightly different awk works fine:
awk -v var="${blah//$'\n'/\\n}" '{sub(/%WORD%/,var)1}'
Recompiling awk is not an option. This is Ubuntu 12.04, 32-bit.
You could use sed
FILE=`cat Filename`
sed "s/WORD/${FILE}/g" file.xml > newfile.xml
Turns out that good old 'replace' out performs awk in this use case--who would have thought?
replace -v "%WORD%" "$blah" -- file.xml
Using Gnu Awk version 4, and the readfile extension:
gawk -f a.awk file.xml
where a.awk is:
#load "readfile"
BEGIN{
var = readfile("blah")
if (var == "" && ERRNO != "")
print("problem reading file", ERRNO) > "/dev/stderr"
}
{
sub(/%WORD%/,var)
print
}