Reputation: 21
I have a file test.file which has following lines.
abc01.hostname.com
xyzabc01.hostname.com
xyzabc02.hostname.com
I have script - for sed which should print output as below
[abc]
abc01.hostname.com
[xyzabc]
xyzabc01.hostname.com
xyzabc02.hostname.com
But I'm getting below output.
[abc]
abc01.hostname.com
[abc]
[xyzabc]
xyzabc01.hostname.com
xyzabc02.hostname.com
Don't know why [abc] is getting duplicated. Any suggestions? below is the script which I am using.
#!/bin/bash
for i in `test.file | cut -d. -f1 | sed 's/[0-9]//g' | uniq`
do
{
name=$(cat test.file | grep ^$i[0-9] | head -1)
sed -i "/$name/i \[$i\]" test.file
}
done
Upvotes: 2
Views: 149
Reputation: 58568
This might work for you (GNU sed):
sed -E 'G;/^([[:alpha:]]+).*\n\1/{P;d};s/\n.*//;h;s/^([[:alpha:]]+).*/[\1]\n&/' file
This solution works by comparing the current key with the previous. The previous key is stored in the hold space and replaced when the key changes. On a change of key the leading alpha characters are converted into an extra record surrounded by [
and ]
. If the key is unchanged, the current record is printed as normal.
Upvotes: 0
Reputation: 212634
I wouldn't use sed
for this. Just do:
awk '$1 != last_prefix {print "[" $1 "]"} 1; {last_prefix=$1}' FS=[0-9] test.file
Upvotes: 2
Reputation: 15418
Let's clean this up a bit.
for i in `cat test.file | cut -d. -f1 | sed 's/[0-9]//g' | uniq`
Don't do this. Don't use a subshell to supply a list to for
, don't use cat
to feed programs that could read the file directly, don't use a long pipeline when the subprocesses aren't needed...
name=$(cat test.file | grep ^$i[0-9] | head -1)
If you are using bash
, there's no nead to run three (technically four?) subprocesses on every iteration to get this edited string. c.f. this page.
#!/bin/bash
last=''
while read name
do label="${name%%[.0-9]*}"
if [[ "$label" != "$last" ]]
then echo "[$label]" # or printf "\n$label\n" for a separator line
last="$label"
fi
echo "$name"
done < test.file > file.redux
Output:
[abc]
abc01.hostname.com
[xyzabc]
xyzabc01.hostname.com
xyzabc02.hostname.com
Then if you are satisfied with the results,
mv file.redux test.file
All handled in bash quickly and efficiently with no spawning until and unless the result is good.
If you think it will be a LOT of data, try awk
with the same logic. :)
Upvotes: 2
Reputation: 6273
You forgot to indicate the start of line also in the sed
command:
#!/bin/bash
for i in `cat test.file | cut -d. -f1 | sed 's/[0-9]//g' | uniq`
do
{
name=$(cat test.file | grep ^$i[0-9] | head -1)
sed -i "/^$name/i \[$i\]" test.file
}
done
Upvotes: 1