Im grepping below file with output below but i want the result to increment it with another number.
egrep -i --color=auto "[0-9]{10}" file
2017080802 ; Xen number
How can I make it to 2017080803 at least?
Something like this?
awk '/[0-9]{10}/ { print 1+$1 }' file
awk '{$1=($1+1); print $0}' file will increment your first column in output.
Exmpl:
a="2017080802 ; Xen number"; echo $a | awk '{$1=($1+1); print $0}'
2017080803 ; Xen number
Related
cat a.txt
a.b.c.d.e.google.com
x.y.z.google.com
rev a.txt | awk -F. '{print $2,$3}' | rev
This is showing:
e google
x google
But I want this output
a.b.c.d.e.google
b.c.d.e.google
c.d.e.google
e.google
x.y.z.google
y.z.google
z.google
With your shown samples, please try following awk code. Written and tested in GNU awk should work in any awk.
awk '
BEGIN{
FS=OFS="."
}
{
nf=NF
for(i=1;i<(nf-1);i++){
print
$1=""
sub(/^[[:space:]]*\./,"")
}
}
' Input_file
Here is one more awk solution:
awk -F. '{while (!/^[^.]+\.[^.]+$/) {print; sub(/^[^.]+\./, "")}}' file
a.b.c.d.e.google.com
b.c.d.e.google.com
c.d.e.google.com
d.e.google.com
e.google.com
x.y.z.google.com
y.z.google.com
z.google.com
Using sed
$ sed -En 'p;:a;s/[^.]+\.(.*([^.]+\.){2}[[:alpha:]]+$)/\1/p;ta' input_file
a.b.c.d.e.google.com
b.c.d.e.google.com
c.d.e.google.com
d.e.google.com
e.google.com
x.y.z.google.com
y.z.google.com
z.google.com
Using bash:
IFS=.
while read -ra a; do
for ((i=${#a[#]}; i>2; i--)); do
echo "${a[*]: -i}"
done
done < a.txt
Gives:
a.b.c.d.e.google.com
b.c.d.e.google.com
c.d.e.google.com
d.e.google.com
e.google.com
x.y.z.google.com
y.z.google.com
z.google.com
(I assume the lack of d.e.google.com in your expected output is typo?)
For a shorter and arguably simpler solution, you could use Perl.
To auto-split the line on the dot character into the #F array, and then print the range you want:
perl -F'\.' -le 'print join(".", #F[0..$#F-1])' a.txt
-F'\.' will auto-split each input line into the #F array. It will split on the given regular expression, so the dot needs to be escaped to be taken literally.
$#F is the number of elements in the array. So #F[0..$#F-1] is the range of elements from the first one ($F[0]) to the penultimate one. If you wanted to leave out both "google" and "com", you would use #F[0..$#F-2] etc.
I write a shell script to abstract data from a file named "POSCAR". It is produced in the win10 system. It looks like this:
System
1.0
23.0000000000 0.0000000000 0.0000000000
0.0000000000 23.0000000000 0.0000000000
0.0000000000 0.0000000000 17.0000000000
C H
24 7
Direct
The 6th and 7th rows are element symbols and number of atoms. I want to get a string = C24H7. So I wrote the script like this:
#!/bin/bash
path=$PWD
fin="POSCAR"
e_tot=`sed -n 6p $fin |awk '{printf "%.1d", NF }'`
echo There are $e_tot columns.
ele=""
for ii in $(seq 1 1 $e_tot)
do
echo $ii
aa=`sed -n 6p $fin |awk -v ll=$ii '{printf "%s", $ll}'`
mm=`sed -n 7p $fin |awk -v ll=$ii '{printf "%d", $ll}'`
col=$aa$mm
ele=$ele$col
done
The output is wield for the last column. I can get C24H, but the "7" is lost. Or it just be exported to the next row.
I thought it may be related to the last character of the row, which is produced by windows and not recognized by Linux, and which I don't know is what.
BEGIN{FS="[ \n\t]+"} for awk does not work.
Where is wrong ?
THANK YOU...
With awk:
awk 'NR==6{a=$1;b=$2}NR==7{print a $1 b $2}' file
C24H7
I am new to using awk i want to separate string contains spaces.
vboxmanage list vms this is my command and its output is below
"VMOne" {5559eb92-2665-4c52-a75d-b57c248c74db}
"VM Second" {9bc754f8-4dfd-44e5-9469-dd824d438832}
my expected output is VMOne;VM Second below is some thing i have tried
vboxmanage list vms | awk '{print $1,";"}' | sed 's/"//g' | awk -vORS="" '1'
but, it gives me output like VMOne ;VM ; it cuts the second word and add a space before ;
any suggestion will helpfull thanks
awk -F\" '{ printf (NR > 1 ? ";%s" : "%s"), $2 } END { if (NR) print "" }' file
Output:
VMOne;VM Second
if (NR) is optional if expected input always has lines. You can also remove the END block completely if you don't need to terminate the output with newline on the end.
I have data of the following form:
num1 This is a string
num2 This is another string
I want to limit length of all strings which are after the first tab..such that length(string)<4. Therefore, the output which I get is:
num1 This is a string
num2 This is another
I can do this using python. But I am trying to find a linux equivalent in order to achieve the same.
In bash, you can use the following to limit the string, in this case, from index 0 to index 17.
$ var="this is a another string"
$ echo ${var:0:17}
this is a another
Using awk, by columns :
$ awk '{print $1, $2, $3, $4}' file
or with sed :
sed -r 's#^(\S+\s+\S+\s+\S+\s+\S+).*#\1#' file
or by length using cut :
$ cut -c 1-23 file
If you'd like to truncate strings on word boundaries, you could use fold with the -s option:
awk -F"\t" '{
printf "%s\t", $1; system(sprintf("fold -sw 17 <<< \"%s\" | sed q", $2))
}'
The drawback is fold and sed need to be called for each line (sed q is the same as tail -n1).
I am trying to get the column names of a file and print them iteratively. I guess the problem is with the print $i but I don't know how to correct it. The code I tried is:
#! /bin/bash
for i in {2..5}
do
set snp = head -n 1 smaller.txt | awk '{print $i}'
echo $snp
done
Example input file:
ID Name Age Sex State Ext
1 A 12 M UT 811
2 B 12 F UT 818
Desired output:
Name
Age
Sex
State
Ext
But the output I get is blank screen.
You'd better just read the first line of your file and store the result as an array:
read -a header < smaller.txt
and then printf the relevant fields:
printf "%s\n" "${header[#]:1}"
Moreover, this uses bash only, and involves no unnecessary loops.
Edit. To also answer your comment, you'll be able to loop through the header fields thus:
read -a header < smaller.txt
for snp in "${header[#]:1}"; do
echo "$snp"
done
Edit 2. Your original method had many many mistakes. Here's a corrected version of it (although what I wrote before is a much preferable way of solving your problem):
for i in {2..5}; do
snp=$(head -n 1 smaller.txt | awk "{print \$$i}")
echo "$snp"
done
set probably doesn't do what you think it does.
Because of the single quotes in awk '{print $i}', the $i never gets expanded by bash.
This algorithm is not good since you're calling head and awk 4 times, whereas you don't need a single external process.
Hope this helps!
You can print it using awk itself:
awk 'NR==1{for (i=2; i<=5; i++) print $i}' smaller.txt
The main problem with your code is that your assignment syntax is wrong. Change this:
set snp = head -n 1 smaller.txt | awk '{print $i}'
to this:
snp=$(head -n 1 smaller.txt | awk '{print $i}')
That is:
Do not use set. set is for setting shell options, numbered parameters, and so on, not for assigning arbitrary variables.
Remove the spaces around =.
To run a command and capture its output as a string, use $(...) (or `...`, but $(...) is less error-prone).
That said, I agree with gniourf_gniourf's approach.
Here's another alternative; not necessarily better or worse than any of the others:
for n in $(head smaller.txt)
do
echo ${n}
done
somthin like
for x1 in $(head -n1 smaller.txt );do
echo $x1
done