So far, I have the following code that allows me to loop through a file and identify the third line of every file. However, I want to delete the last column on every third line, but I'm having trouble coming up with the syntax:
#!/bin/bash
counter=1
lines=$(wc -l < 'test_file')
echo $lines
while read line; do
if (( $counter % 3 == 0 )); then
#Need a good one liner here to solve the problem!
else
echo "$line is not a multiple of three."
fi
((counter = counter + 1))
done < 'test_file'
I'm open to using awk, but I'm not sure how to do that inline on a line within a file. If it can be done with parameters on the entire file that is fine.
Also, if the divisible by 3 line contains only one field, that should be deleted as well. There will never be an already existing blank line.
Sample input:
my dog smells
my cat bites
my fish swims
a b c
d e f
g h i
Sample output:
my dog smells
my cat bites
my fish
a b c
d e f
g h
awk is easier to handle this kind of task:
awk 'NR%3==0{NF--}7' file
let's do a little test:
kent$ cat f
a b c d
a b c d
a b c d
a b c d
a b c d
a b c d
a b c d
a b c d
a b c d
a b c d
kent$ awk 'NR%3==0{NF--}7' f
a b c d
a b c d
a b c
a b c d
a b c d
a b c
a b c d
a b c d
a b c
a b c d
This might work for you (GNU sed):
sed '3~3s/\s\S\+$//' file
Related
I have two blocks of data in a file, say foo.txt like the following:
a 1
b 2
c 3
d 4
e 5
f 6
g 7
h 8
i 9
I'd like to extract rows 2:4 and 6:8 and put them as the following:
b 2 f 6
c 3 g 7
d 4 h 8
I could try using auxiliary files:
sed -n '2,4p' foo.txt > tmp1; sed -n '6,8p' foo.txt > tmp2; paste tmp1 tmp2 > output; rm tmp1 tmp2
But is there a better way to do it without auxiliary files? Thanks!
Using process substitution:
$ paste <(sed -n '2,4p' foo.txt) <(sed -n '6,8p' foo.txt) > output
$ cat output
b 2 f 6
c 3 g 7
d 4 h 8
$
In AWK:
$ awk 'NR==2,NR==4{a[++i]=$0} NR==6,NR==8{b[++j]=$0} END {for(i=1;i<=j;i++) print a[i],b[i]}' file
b 2 f 6
c 3 g 7
d 4 h 8
When between the given record numbers (NR), fill up arrays a and b. In the END, print them side by side.
I want to compare two columns in a file as below using AWK, can someone gives a help please?
e.g.
Col1 Col2
---- ----
2 A
2 D
3 D
3 D
3 A
7 N
7 M
1 D
1 R
Now I want to use AWK to implement the following algorithm to find matches between those columns:
list1[] <=== Col1
list2[] <=== Col2
NewList[]
for i in col2:
d = 0
for j in range(1,len(col2)):
if i == list2[j]:
d++
NewList.append(list1[list2.index[i]])
Expected result:
A ==> 2 // means A matches two times to Col1
D ==> 4 // means D matches two times to Col1
....
So I want to write the above code in AWK script and I find it too complicated for me as I haven't used it yet.
Thank you very much for your help
Not all that complicated, keep the count in an array indexed by the character and print the array out at the end;
awk '{cnt[$2]++} END {for(c in cnt) print c, cnt[c]}' test.txt
# A 2
# D 4
# M 1
# N 1
# R 1
{cnt[$2]++} # For each row, get the second column and increase the
# value of the array at that position (ie cnt['A']++)
END {for(c in cnt) print c, cnt[c]}
# When all rows done (END), loop through the keys of the
# array and print key and array[key] (the value)
alternative solution
$ rev file | cut -c1 | sort | uniq -c
2 A
4 D
1 M
1 N
1 R
for the formatting pipe to ... | sed -r 's/(\w) (\w)/\2 ==> \1/'
A ==> 2
D ==> 4
M ==> 1
N ==> 1
R ==> 1
Or, do everything in awk
I am looking for some effective way to concatenate multiple multiline files into one file - here is an example for three input files:
1.txt:
a b
c d
2.txt:
e f
g
h
3.txt:
ijklmn
output.txt:
a b c d
e f g h
ijklmn
(Replacing each linebreak with single whitespace). Which way can you recommend?
Using BASH for loop:
for i in [0-9]*.txt; do tr '\n' ' ' < "$i"; echo; done > output.txt
cat output.txt
a b c d
e f g h
ijklmn
If you want to strip one ending space before each line break then use:
for i in [0-9]*.txt; do tr '\n' ' ' < "$i"; echo; done | sed 's/ *$//' > output.txt
I have this script cut -d "|" -f 8,9,13,23 info.txt > result.txt
When I open result.txt it looks like this:
R S L T = R A C 2 6 8 | R A W T = r i c k a r d a d a m c e s a r t w o s i x n i n e
When it should look like this:
RSLT=RAC268|RAWT=rickard adam cesar two six nine
It works in the console, so my guess is that the problem is within the output operator.
I have the following text file:
A,B,C
A,B,C
A,B,C
Is there a way, using standard *nix tools (cut, grep, awk, sed, etc), to process such a text file and get the following output:
A
A
A
B
B
B
C
C
C
You can do:
tr , \\n
and that will generate
A
B
C
A
B
C
A
B
C
which you could sort.
Unless you want to pull the first column then second then third, in which case you want something like:
awk -F, '{for(i=1;i<=NF;++i) print i, $i}' | sort -sk1 | awk '{print $2}'
To explain this, the first part generates
1 A
2 B
3 C
1 A
2 B
3 C
1 A
2 B
3 C
the second part will stably sort (so the internal order is preserved)
1 A
1 A
1 A
2 B
2 B
2 B
3 C
3 C
3 C
and the third part will strip the numbers
You could use a shell for-loop combined with cut if you know in advanced the number of columns. Here is an example using bash syntax:
for i in {1..3}; do
cut -d, -f $i file.txt
done
Try:
awk 'BEGIN {FS=","} /([A-C],)+([A-C])?/ {for (i=1;i<=NF;i++) print $i}' YOURFILE | sort