How to change a character in a specific line of a

2019-09-20 10:29发布

问题:

I have a .bd document which has lines for each book that I have. Each book has the title, author, etc divided by a \t. The last character of each line can be 1 or 0 depending on whether the book is borrowed or not. I need a way to change that number change the state of a book by using the id (first number of the line).

1   title1  author1 genre1  year1   shelv1  0
2   title2  author2 genre2  year2   shelv2  0
3   title3  author3 genre3  year3   shelv3  0

回答1:

To change status of id 2 to 1:

awk -v id=2 -v status=1 'BEGIN{FS=OFS="\t"} $1==id {$NF=status}1' file

Output:

1       title1  author1 genre1  year1   shelv1  0
2       title2  author2 genre2  year2   shelv2  1
3       title3  author3 genre3  year3   shelv3  0

See: 8 Powerful Awk Built-in Variables – FS, OFS, RS, ORS, NR, NF, FILENAME, FNR



回答2:

based on the assumption that all ids are integers:

$ awk -v ids='1 3' '
BEGIN{FS=OFS="\t"}
ids~"(^| )"$1"( |$)"{$NF=!$NF}
1' file
1       title1  author1 genre1  year1   shelv1  1
2       title2  author2 genre2  year2   shelv2  0
3       title3  author3 genre3  year3   shelv3  1

to update file with above command's output:

awk ... file > tmpfile && mv tmpfile file

note that above script is not scalable at all, it will take too much time to process a file consisting of >1000 lines. if you need an efficient one and won't mind its length, here it is:

awk -v ids='1 3' '
BEGIN {
  split(ids,p)
  for(i in p) q[p[i]]
  FS=OFS="\t"
}
($1 in q) {
  $NF=!$NF
}
1' file

I also wrote one that doesn't create two arrays but then thought it isn't worth it.



标签: shell awk