Tag Info

Hot answers tagged

8

Your awk syntax is a little wrong. #!/bin/bash awk -F: -v keyword="$1" '$1 == keyword {$1=$1; print}' myfile.csv The trick here is reassigning the value of one of the fields forces awk to recalculate $0 using the output file separator. Here, the default OFS is a space, so assigning the value of $1 to itself changes the colons to spaces. A non-awk way to ...


8

id also accepts paramters, so you don't have to grep for it (-g to print only the group, and -n to print names instead of ids): $ id -gn usera groupa To save that into a variable use that: groupname=$(id -gn usera)


7

You can use Bash's parameter expansion: string="foo-bar-123" && printf "%s\n" "${string##*-}" 123 If you want to use another process, with Awk: echo "foo-bar-123" | awk -F- '{print $NF}' Or, if you prefer Sed: echo "foo-bar-123" | sed 's/.*-//' A lighter external process, as Glenn Jackman suggests is cut: cut -d- -f3 <<< "$string" ...


6

You're being bitten by a floating point arithmetic issue. $ awk 'BEGIN { printf "%.17f\n", 99.15-20.85 }' 78.30000000000001137 http://floating-point-gui.de/ might be able to help clear things up for you - it tries to explain what floating point is, and why arithmetic errors like this happen, and how to avoid these sorts of issues in your programs.


6

I doubt it will make a difference but, just in case, here's how to do the same thing in Perl: perl -ne 'print if ++$k{$_}==1' out.txt If the problem is keeping the unique lines in memory, that will have the same issue as the awk you tried. So, another approach could be: cat -n out.txt | sort -k2 -k1n | uniq -f1 | sort -nk1,1 | cut -f2- How it works: ...


6

I don't think that [ -d ] is an awk thing, that's a shell thing. I would just do it this way instead: awk -F: '{ print $1,$3,$7}' /etc/passwd | while read name uid shell; do [ -d "/home/$name" ] || echo "$name $uid $shell"; done Of course, as very correctly pointed out by @Janis, you can do the whole thing in the shell: while IFS=: ...


6

You could use system(command) Execute the operating-system command command and then return to the awk program. Return command’s exit status. e.g.: awk -F: '{if(system("[ ! -d " $6 " ]") == 0) {print $1 " " $3 " " $7}}' /etc/passwd


5

Another perl: print a line if there are 3 commas. perl -i.bak -ne 'print if tr/,/,/==3' file The tr operator returns the number of characters transliterated.


5

I would split the line on dots and remove the last 4 fields awk -F. -v OFS=. '{NF-=4}1' But Costas's code in his comment more directly answers the requirements.


4

Try standard regexps (instead of perl regexps). This will print matching lines: awk '/\[[[:digit:]]+\]/ { print }' maillog To extract and print the matching value inside the brackets: awk 'match($0,/\[[[:digit:]]+\]/) { print substr($0,RSTART+1,RLENGTH-2)}' maillog


4

Starting off with a basic file here... $ cat file location 100 Number location 101 Number location 102 Number We can match on all lines: $ awk '{print $0 NR}' file location 100 Number1 location 101 Number2 location 102 Number3 it gets more complicated if there is filler somewhere in the middle. You have to have a separate counter tallying up the ...


4

The floating point numbers 99.15 and 28.85 and 78.30 don't have exact IEEE 754 binary representations. You can see this with a C program that does the same calculation: #include <stdio.h> int main(int ac, char **av) { float a = 99.15; float b = 20.85; float c; printf("a = %.7f\n", a); printf("b = %.7f\n", b); ...


4

#!/usr/bin/perl use DB_File; tie %h, 'DB_File'; while(<>){ not $h{$_} and print and $h{$_}=1 } EDIT 1: Does it really work? (comparing) Sol1 : Terdon et all Schwartzian-transform-like one-liner cat -n _1 | sort -uk2 | sort -nk1 | cut -f2- Sol2 : perl + DB_File (this answer) perl dbfile-uniq _1 Sol3 : PO (John W. Gill solution has a ...


4

It is almost awk... perl -F: -ane 'if(!-d $F[5]){ print "$F[0] $F[2] $F[6]" }' /etc/passwd


4

find is an executable not an awk function. S, if you want to call an executable within awk, you have to do that with the system() function. cmd | awk '{system("find " $6 " -xdev -type f -perm -4000 -print")}'


4

This counts the number of ones and zeros in filename: $ sort <filename | uniq -c 5 0 5 1


4

Use either of the two patterns: NR>6 { this_code_is_active } or this: NR<=6 { next } { this_code_is_active } Use FNR instead of NR if you have many files as arguments to awk and want to skip 6 lines in every file.


4

The main problem has already been highlighted by don_crissti in his comment. He determined the file type by running: file koran ... which outputs: ASCII C++ program text, with CRLF, LF line terminators You need to remove the CR (Carriage Return - hex value \x0D) characters which are present at the end of some lines in your input file. This CR is ...


3

With perl: $ perl -F, -i.bak -ane 'print if @F > 3' file With perl > 5.20, you can use -F without -a and -n (-F implies -a and -a implies -n). Or you can use sed: $ sed -i.bak -e '/\([^,]*,\)\{3,\}/!d' file


3

You can use awk: awk -F',' 'NF==4' file If you can use gawk version >= 4.1.0 you can use inplace, more info. So it could be: gawk -i inplace -v INPLACE_SUFFIX=.bak -F',' 'NF==4' file


3

Why are you using awk for this? If you have both the original and the target name, why not just mv abc.txt begperl/ab.txt? If you don't have the target name and just want to remove a character from the original, you can do it in the shell. Again, no need for awk: file="abc.txt"; mv "$file" begperl/"${file//c}" That will remove all occurrences of c from ...


3

You need the sub (substitute) rather than the substr (substring) command: compare $ awk -v name="abc.txt" 'BEGIN {substr("c","",name) ; print name}' abc.txt with $ awk -v name="abc.txt" 'BEGIN {sub("c","",name) ; print name}' ab.txt However unless you are doing this as a programming exercise to learn awk, there really is no reason not to use your shell ...


3

Your Awk pattern is failing because the word "profile" does not start the record, [profile does... awk '/^\[profile/ {gsub(/]/,""); print $2}' test.txt dev prod Another approach would be to load an array, using split: awk -F'[][]' '/profile/ {p=split($2,profiles," "); print profiles[2]}' test.txt dev prod


3

2 thoughts: with sed, for any line that ends with a carriage return, join the next line sed '/\r$/ {N; s/\r\n//} ' file with awk, define the record separator for input and output: awk -v RS='\r\n' -v ORS='' 1 file


3

You can avoid such kind of mistakes by numbers formating: awk -F, '{ if (NR != 1 && sprintf(CONVFMT,prior_tot-$1) != $2) {print "Arithmetic fail..." $0} else {print "OK"} prior_tot = $2}'


3

My solution using join: join -a1 -a2 -1 1 -2 1 -o 0,1.2,2.2 -e "NULL" file1 file2 I don't know much about awk for joining large files and always use join. key1 11 NULL key2 12 22 key3 13 23 key4 NULL 24 key5 NULL 25


3

You could use a BEGIN block to set a flag unset the flag when your current test finds a missing directory check to see if the flag is still set in a END block and if so print your message e.g. awk -F: ' BEGIN{nores=1;} {if(system( "[ -d " $6 " ]") == 1 && $7 != "/sbin/nologin" ) {print "The directory " $6 " does not exist for user " $1; nores=0 ...


3

flag=0 testuser=$(stat "/home/testuser" -c %U) while IFS=':' read -r myuser a b c d mydir e do if [ -d "$mydir" -a "$e" != "/sbin/nologin" ] then if [ "$myuser" != "$testuser" -a \ "$myuser" != $(stat "$mydir" -c %U) ] then echo "The directory $mydir exists for user $myuser" \ "but is not ...


3

The reason it's faililng is because you are only printing the variables you capture once, in an END{} block. This means that only the last two will be printed. @Costas already gave you a more elegant approach, but you could also use the same logic you were trying with a small change: awk '{ if(/Node/){ if(length(n)){print n,l} ## if we have an n, ...


3

Here is a sed alternative: sed -n '/^def:/s/:/ /gp' myfile.csv If you pass the string as first positional parameter: sed -n "/^$1:/s/:/ /gp" myfile.csv



Only top voted, non community-wiki answers of a minimum length are eligible