How do I grep non-zero words in a file? - bash

I want to grep all strings that are not 0 in a file. Is there a way to do that?
The file looks something like the following:
0
0
0
0.12
0
0
and I would like the output to be:
0.12

You can with awk do:
awk '$1' file
This will skip all lines with 0 in it.
If you like print all words without 0 then try this:
awk '{for (i=1;i<=NF;i++) if ($i!~/0/) printf "%s ",$i;print ""}' file

Related

Most efficient way to use first column of file1 as prefix for all lines in file2

I have two files with equal amount of lines. I want to add each value of column 1 to become the prefix of each line in file 2 and separate each value of file2 by one whitespace.
File2 is very large and has more than 70 million columns.
Example:
Input file 2
10000
10019
Input file 1
Ind1
Ind2
Output
Ind1 1 0 0 0 0
Ind2 1 0 0 1 9
Q: How can this be done efficiently?
EDIT I : I already looked for solutions to add different prefixes to each line e.g. here but was unable to adjust the solution so that I can iterate over the values of the first column of another file.
EDIT II :
Using the answer from #Gilles I came up with this:
awk ' { print $1 } ' file1 <(sed 's/./& /g' file2) > output
EDIT III:
I tried the solution from #Gilles and it failed with a regex input buffer error:
paste -d ' ' file1 <(sed 's/./& /g' file2) > file3
sed: regex input buffer length larger than INT_MAX
I also tried the solution from #Ed Morton but this ended in an OOM error. AWK states that it needs 1.8TB RAM for this operation.
awk '{head=$0} (getline tail < "file2") > 0{gsub(/./," &",tail); print head tail}' file1 > file3
awk: cmd. line:1: (FILENAME=file1.txt FNR=1) fatal: builtin.c:3058:sub_common: buf: cannot reallocate 1949336035328 bytes of memory: Cannot allocate memory.
Using sed & paste:
$ paste -d '' file2 <(sed 's/./& /g' file1)
Ind1 1 0 0 0 0
Ind2 1 0 0 1 9
Using any awk:
$ awk '{head=$0} (getline tail < "file2") > 0{gsub(/./," &",tail); print head tail}' file1
Ind1 1 0 0 0 0
Ind2 1 0 0 1 9
or if the whole contents of file1 fit in memory:
$ awk 'NR==FNR{a[FNR]=$0; next} {gsub(/./," &"); print a[FNR], $0}' file1 file2

Modify the column of a text file

I would like to change the second column of a text file,named as subject.txt, containing "1" and "2" to "0" and "1" using bash. Any suggestion? I am new to bash and any help would appreciate it.
Subj1 1
Subj2 2
Subj3 1
I would like to change it to:
Subj1 0
Subj2 1
Subj3 0
You can use awk:
cat subject.txt | awk '{ $2=$2-1; print $1" "$2 }'
restrict modifications only for 1 and 2
$ awk '$2==1 || $2==2 {$2--}1' file

How can I use awk to detect lines that have only one field and print it together with the next line?

I've a file.txt written in this way:
0
0.421915 0.420615 192000
0.420397 0.420802 192000
1
0.423915 0.423681 768000
0.421658 0.421474 768000
and I'd like to take the line with only one column and the following one.
Is it ok to use awk and how can I do it?
Thank you!
Short awk approach:
awk 'NF==1 && (getline nl)>0{print $0 ORS nl}' file
The output:
0
0.421915 0.420615 192000
1
0.423915 0.423681 768000
NF==1 - considering only lines with one column
getline nl - getting the next line and assigning it to variable nl (next line)
(getline nl)>0 - the getline command returns 1 if it finds a record and 0 if it encounters the end of the file
print $0 ORS nl - print the line with only one column and the following one (as required)
I would do it with grep :
grep -E -A 1 "^[0-9]+$" yourfile.txt
You should be able to do it with:
awk 'NF==1{p=1;print$0;}NF!=1{if(p==1){print$0;p=0}}' file.txt
Output:
0
0.421915 0.420615 192000
1
0.423915 0.423681 768000
$ awk 'NF==1{c=2} c&&c--' file
0
0.421915 0.420615 192000
1
0.423915 0.423681 768000
See https://stackoverflow.com/a/17914105/1745001 for an explanation of that and more awk range idioms.

How to find negaive numbers from each line and print only once using shell script

I want to find the negative numbers (same value) from each row of an input file.
If there is no negative numbers in a row it will print 0. If there is more than one occurrence of a negative number it will print the negative number once. For example
the input file is (input.txt):
1 0 0 0 0 0 0 0 0
1 1 -1 0 -1 0 1 0 0
1 1 0 -1 0 0 1 0 -1
1 1 0 0 -1 0 0 0 0
The desired output is :
0
-1
-1
-1
Currently I am using
awk '{for(i=1; i<=NF;i++)if($i ~ /^-/) {printf "%s\n",$i}}' input.txt > output
But it does not produce the 0 in the 1st line and it prints all the -1s.
Is there a smart solution to this problem?
You can do this with simple pattern matching in bash, no need for awk.
while read line; do
if [[ $line = *-1* ]]; then
echo -1
else
echo 0
fi
do < inputfile
Or shortened to a one-liner:
while read l; do [[ $l = *-1* ]] && echo -1 || echo 0; done < inputfile
Or sed could do this:
sed '/-/s/.*/-1/;/-/!s/.*/0/' inputfile
Or if you're willing to trade simplicity for performance:
sed -e '/-/s/.*/-1/;t' -e 's/.*/0/' inputfile
You can use this awk:
awk '{p=0; for(i=1; i<=NF;i++) if ($i<0) {p=$i; break} print p}' file
0
-1
-1
-1
$ awk '{print (/-/?-1:0)}' file
0
-1
-1
-1
I assume that either:
you can't have a row with, say, -2s instead of -1s, or
if that does occur you still want -1 output
since if it could happen that you have rows of -2s instead of -1s and want -2 to be output in that case then that would have been a glaringly obvious thing to include in your sample input/output.
Based on your problem description, you may use this:
awk '/-/{print "-1"}!/-/{print "0"}' file

awk show just digits

I have command in awk:
awk '$0 !~ /[a-z]/ && $0 != 0' input.txt >> output.txt
So my input is something like this:
123214
wedsd
sda25567
ssdf
!#!###%
And my output is:
123214
!#!###%
I think I am doing something wrong with awk.
I want awk just show me digits, What should I do?
Thanks
This !#!###% does not contain a-z and its not 0
That is why you get hits on it.
To get only numbers, use anchor:
awk '/^[[:digit:]]+$/' file
123214
or
awk '/^[0-9]+$/' file
try this:
awk '/^[0-9]+$/ && $0 != 0 {print}' input.txt >> output.txt

Resources