简体   繁体   中英

Inserting a matched string from previous line to the current line using sed or awk

I have a CSV file that shows the statistics for links on a half an hour basis. The link name only appears on the 00:00 line.

link1,0:00,0,0,0,0
,00:30,0,0,0,0
,01:00,0,0,0,0
,01:30,0,0,0,0
,02:00,0,0,0,0
,02:30,0,0,0,0
,03:00,0,0,0,0
,03:30,0,0,0,0
,23:30,0,0,0,0
....
....
link2,00:00,0,0,0,0

How do I copy the link name to every other line until the link name is different, using sed or awk?

With awk , just keep track of the last seen non-empty link name, and always use that.

awk -F, -v OFS=, '$1 != "" { link=$1 } { $1 = link; print $0 }'

Omitting the ellipses, this gives:

link1,0:00,0,0,0,0
link1,00:30,0,0,0,0
link1,01:00,0,0,0,0
link1,01:30,0,0,0,0
link1,02:00,0,0,0,0
link1,02:30,0,0,0,0
link1,03:00,0,0,0,0
link1,03:30,0,0,0,0
link1,23:30,0,0,0,0
link2,00:00,0,0,0,0

This is a simpler job with awk, but if you want to use sed:

sed -e '/^[^,]/{h;s/,.*//;x};/^,/{G;s/^\(.*\)\n\(.*\)/\2\1/}'

Bellow a commented version in sed script file format that can be run with sed -f script :

# For lines not beginning with a ',', saves what precedes a ',' in the hold space and print the original line.
/^[^,]/{
h
s/,.*//
x}
# For lines beginning with a ',', put what has been save in the hold space at the beginning of the pattern space and print.
/^,/{
G
s/^\(.*\)\n\(.*\)/\2\1/}

You can do that in pure bash shell without needing to start a new process, which should be faster than using awk or sed:

IFS=","
while read v1 v2; do
  if [[ $v1 != "" ]]; then
    link=$v1;
  fi
  printf "%s,%s\n" "$link" "$v2"
done < 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM