I have a $FILE
1 textline1
1 textline2
1 textline3
1 textline4
I want to search for textline3 and make sum: 1stcolumn+1
Linenumber is:
lnr=$(grep -n textline3 $FILE | cut -d : -f1)
But when i use awk:
awk -v l="$lnr" 'FNR==l{ sub($1,$1 + 1); print }1' $FILE
I get the erroneous (3rd line is double printed)
1 textline1
1 textline2
2 textline3
2 textline3
1 textline4
Reason for double printing is , you are printing inside {} and using 1 as well. 1 means true and awk's default behaviour is to print.
awk -v l="$lnr" 'FNR==l{ sub($1,$1 + 1)}1' $FILE
You can avoid the usage of grep
and let awk
do the magic.
awk '/textline3/{sub($1,$1 + 1)}1' file
1 textline1
1 textline2
2 textline3
1 textline4
In general, you can do a awk '/<pattern>/ { <action> }' file
for manipulation.
If you just want to increment the first field on the N th line, just say so:
$ awk -v line=3 'FNR==line {$1+=1}1' file # line is more readable than l
1 textline1
1 textline2
2 textline3
1 textline4
Note the 1
here is triggering awk
's default action, consisting in printing the current line. For every line it will print the initial value but for the line number line
it will print the 1 st value with its value +1.
And that's why you see that line twice in your code: because in the action triggered by FNR==line
you are already calling print
.
Theres a few problems with your script:
print
inside the action block and then the 1
at the end of the script is a constant true condition which will cause awk to execute it's default action of printing the record again. l
(el) as a variable name, it looks far too much like the number 1
(one) and so makes your code harder to read. $1
, just do $1++
(assuming textline3
doesn't contain chains of white space that must not be concatenated into one blank char). $1
) as either the search regexp or replacement string fields of any *sub() command as that will fail cryptically given various regexp or backreference metacharacters in the input. So your script should be just:
$ awk '/textline3/{$1++}1' file
1 textline1
1 textline2
2 textline3
1 textline4
Solution using perl
$ perl -pe 's/^(\d+)(?=\s*textline3)/$1+1/e' $FILE
1 textline1
1 textline2
2 textline3
1 textline4
or
perl -pe 's/^(\d+)/$1+1/e if /textline3/' $FILE
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.