I have a requirement to cut a file name into two parts.
So my file name is : 'SIC_ETL_MAIN_0.1.zip'
I want to cut the file name into parts and load into two variable separately
Expected Output:
SIC_ETL_MAIN - var1
0.1 - var2
using grep
$echo SIC_ETL_MAIN_0.1.zip | grep -o '[A-Z_]*[A-Z]'
SIC_ETL_MAIN
$echo SIC_ETL_MAIN_0.1.zip | grep -o '[0-9\.]*[0-9]'
0.1
$
Edit: Variable assignment
$var1=$(echo SIC_ETL_MAIN_0.1.zip | grep -o '[A-Z_]*[A-Z]')
$var2=$(echo SIC_ETL_MAIN_0.1.zip | grep -o '[0-9\.]*[0-9]')
$echo "Var1=${var1} Var2=${var2}"
Var1=SIC_ETL_MAIN Var2=0.1
$
If your shell happens to be bash (or another shell wit shubstrings)
a=SIC_ETL_MAIN_0.1.zip
b=${a%_*}
c=${a##*_}
d=${c%.*}
echo "$a | $b | $c | $d" # will output
SIC_ETL_MAIN_0.1.zip | SIC_ETL_MAIN | 0.1.zip | 0.1
Related
There are lots of files in a directory and output to be group and sort like below,first exe files
without any file extension,then sql files ending with "body",then sql files ending with "spec",then
other sql files.then "sh" then "txt" files.
abc
1_spec.sql
1_body.sql
2_body.sql
other.sql
a1.sh
a1.txt
find . -maxdepth 1 -type f ! -name "*.*"
find . -type f -name "*body*.sql"
find . -type f -name "*spec*.sql"
Getting difficult to combine all and sorting group with order.
with ls, grep and sort you could do something like this script I hacked together:
#!/bin/sh
ls | grep -v '\.[a-zA-Z0-9]*$' | sort
ls | grep '_body.sql$' | sort
ls | grep '_spec.sql$' | sort
ls | grep -vE '_body.sql$|_spec.sql$' | grep '.sql$' | sort
ls | grep '.sh$' | sort
ls | grep '.txt$' | sort
normal ls:
$ ls -1
1_body.sql
1_spec.sql
2_body.sql
a1.sh
a1.txt
abc
bar.sql
def
foo.sh
other.sql
script
$
sorting script:
$ ./script
abc
def
script
1_body.sql
2_body.sql
1_spec.sql
bar.sql
other.sql
a1.sh
foo.sh
a1.txt
$
I need to get this result having this format :
"hadoop fs -ls -d -C -t /hdfs/data/t1/t11/34/1EX4/ | grep indicateurs-PUB_1ELPC | grep "^d" | sort -k6,7 | tail -1 | tr -s ' ' | cut -d' ' -f8 "
So I tried to use this instruction :
paste0("hadoop fs -ls -d -C -t /hdfs/data/t1/t11/34/1EX4/ | grep indicateurs-PUB_","1ELPC",cat(" grep \"^d\" | sort -k6,7 | tail -1 | tr -s ' ' | cut -d' ' -f8 "),sep = "")
But, this return
grep "^d" | sort -k6,7 | tail -1 | tr -s ' ' | cut -d' ' -f8 [1] "hadoop fs -ls -d -C -t /hdfs/data/t1/t11/34/1EX4/ | grep indicateurs-PUB_1EPSE"
So, the problem is about using the cat function, In fact I need that its result will be in quoted format. In other way, I can't understand why the result was inversed here ?
I'm assuming you split up the arguments to paste0 for a specific reason. As #RuiBarradas mentions - cat is for printing, but not returning an actual object (always returns NULL):
paste0("hadoop fs -ls -d -C -t /hdfs/data/t1/t11/34/1EX4/ | grep indicateurs-PUB_",
"1ELPC",
" grep \"^d\" | sort -k6,7 | tail -1 | tr -s ' ' | cut -d' ' -f8 ",
sep = "")
returns:
[1] "hadoop fs -ls -d -C -t /hdfs/data/t1/t11/34/1EX4/ | grep indicateurs-PUB_1ELPC grep \"^d\" | sort -k6,7 | tail -1 | tr -s ' ' | cut -d' ' -f8 "
which looks to me like what you want.
Do note that, in the output \" is one character (a double quote). i.e.,
> nchar("\"")
[1] 1
To further illustrate the point:
temp <- paste0("hadoop fs -ls -d -C -t /hdfs/data/t1/t11/34/1EX4/ | grep indicateurs-PUB_",
"1ELPC",
" grep \"^d\" | sort -k6,7 | tail -1 | tr -s ' ' | cut -d' ' -f8 ",
sep = "")
> cat(temp)
hadoop fs -ls -d -C -t /hdfs/data/t1/t11/34/1EX4/ | grep indicateurs-PUB_1ELPC grep "^d" | sort -k6,7 | tail -1 | tr -s ' ' | cut -d' ' -f8
> print(temp, quote = FALSE)
[1] hadoop fs -ls -d -C -t /hdfs/data/t1/t11/34/1EX4/ | grep indicateurs-PUB_1ELPC grep "^d" | sort -k6,7 | tail -1 | tr -s ' ' | cut -d' ' -f8
how can the cut command return value left to 2nd last delimiter starting from the right side.
$ echo 'qwertyuiop.abcdefgh.1234567890.txt' | cut -d '.' -f 1,2
qwertyuiop.abcdefgh
$ echo 'qwertyuiop.1234567890.txt' | cut -d '.' -f 1,2
qwertyuiop.1234567890
$
expected output for both
qwertyuiop.abcdefgh
qwertyuiop
You can reverse your string with the rev command and then cut from the third field to the end, reversing at the end.
$ echo 'qwertyuiop.abcdefgh.1234567890.txt' | rev | cut -d '.' -f 3- | rev
qwertyuiop.abcdefgh
$ echo 'qwertyuiop.1234567890.txt' | rev | cut -d '.' -f 3- | rev
qwertyuiop
I may not have got the title perfect for this question, but I am wondering if there is a way to do the following :
Basically, I have a text file with some key value pairs and also a statement (in the same text file) which will be extracted by a shell script and which needs to also simultaneously substitute the A, B, C in the STATEMENT variable .
To make things simple, let me provide an example.
Here is my text file :
File : values.txt
A=1
B=2
C=3
STATEMENT=apple A orange B grape C
Also, I have a shell script which extracts these values and the statement from the text file and uses the STATEMENT variable as a parameter to another script it calls, something like:
Script : first_script.sh
A=`cat values.txt | grep -w '^A' | cut -d'=' -f2`
B=`cat values.txt | grep -w '^B' | cut -d'=' -f2`
C=`cat values.txt | grep -w '^C' | cut -d'=' -f2`
STATEMENT=`cat values.txt | grep -w 'STATEMENT' | cut -d'=' -f2`
second_script.sh $STATEMENT
As you can see, second_script is called from within first_script and it uses the STATEMENT variable, so what I expect to see with the second_script call is :
second_script.sh apple 1 orange 2 grape 3
Note that "A", "B" and "C" should get substituted to their values 1, 2 and 3.
However, what I get is still :
second_script.sh apple A orange B grape C
which is what I don't want.
How do I make sure that A, B and C get substituted to 1,2 and 3 respectively when second_script is called from first_script ?
Sorry to make it confusing.
You can substitute values in a string like this:
STATEMENT=${STATEMENT/A/$A} # replace the letter A with the value of $A
STATEMENT=${STATEMENT/B/$B}
STATEMENT=${STATEMENT/C/$C}
second_script.sh "$STATEMENT"
If you want to match word boundaries use sed:
STATEMENT=$(sed -e "s/\bA\b/$A/g" -e "s/\bB\b/$B/g" -e "s/\bC\b/$C/g" <<< "$STATEMENT")
Also, you don't need to use cat in your script. You can do it like this:
A=`grep -w '^A' values.txt | cut -d'=' -f2`
Or, using awk:
A=$(awk -F= '/^A\y/{print $2}' values.txt)
Alternatively:
Are you able to change the values.txt file?
It would be easier if you could change it to:
A=1
B=2
C=3
STATEMENT="apple $A orange $B grape $C"
Then in your script you could simply import the file like this:
. values.txt
second_script.sh "$STATEMENT"
How about this:
#!/bin/bash
tail -1 values.txt | {
IFS='=' read name statement
./second_script.sh $(echo "$statement" | sed -r $(
head --lines=-1 values.txt | while IFS='=' read name value
do
printf "%s s/\<%q\>/%q/g " "-e" "$name" "$value"
done))
}
I don't like hard coded solutions, so this will read the values.txt file and evaluate all variables (all but last line) in the statement (last line) and give this to the second_script.sh.
I'd be careful about names and values containing special characters like spaces etc. Run thorough test if you plan on using these!
The Unix cut command takes a list of fields, but not the order that I need it in.
$ echo 1,2,3,4,5,6 | cut -d, -f 1,2,3,5
1,2,3,5
$ echo 1,2,3,4,5,6 | cut -d, -f 1,3,2,5
1,2,3,5
However, I would like a Unix shell command that will give me the fields in the order that I specify.
Use:
pax> echo 1,2,3,4,5,6 | awk -F, 'BEGIN {OFS=","}{print $1,$3,$2,$5}'
1,3,2,5
or:
pax> echo 1,2,3,4,5,6 | awk -F, -vOFS=, '{print $1,$3,$2,$5}'
1,3,2,5
Or just use the shell
$ set -f
$ string="1,2,3,4,5"
$ IFS=","
$ set -- $string
$ echo $1 $3 $2 $5
1 3 2 5
Awk based solution is elegant. Here is a perl based solution:
echo 1,2,3,4,5,6 | perl -e '#order=(1,3,2,5);#a=split/,/,<>;for(#order){print $a[$_-1];}'