简体   繁体   中英

escape sed in shell script

I wish to put some numbers in my result txt files using shell script and sed, like:

for i in 0.88 0.90 0.92 0.94 0.96 0.98 1.00 1.02 1.04 1.06 1.08 1.10 1.12; do
    a_original_A=5
    amod=`bc <<< "$i*$a_original_A"`
    sed -s -i '1i|/\"list_number_$i  $amod  $amod  $amod  90  90  90" ' list_${i}.txt
    sed -s -i '1i\12' list_${i}.txt
done

But it didn't work. I tried to use sed with escaping, but failed; I tried

sed -s -i '1i|/\"list_number_$i  ${amod}  ${amod}  ${amod}  90  90  90" ' list_${i}.txt

But this doesn't help as well.

Here, I wish to make 13 number of txt files, and wish to put changing numbers at the second line of 13 txt files. For example, list_0.88.txt contains

12
list_number_0.88    4.4   4.4   4.4   90   90   90

Those two lines at the beginning of the file. 4.4 is coming from 5*0.88. Likewise, I wish to make 13 files, to have different numbers in 2nd line. How can I use numbers in sed command?

NB: There are already 13 non-empty text files; I wish to add these new lines as the first two lines in each of the existing files.

First , you have "list_0.88.txt , list_0.90.txt ... " , and so on , right ? As your wish , I think we can modify the shell like that:

#!/bin/bash

for i in "0.88 0.90 0.92 0.94 0.96 0.98 1.00 1.02 1.04 1.06 1.08 1.10 1.12"
do
        a_original_A=5
        amod=`bc <<< "$i*$a_original_A"`
        echo "---->$amod"
        echo "12" > /tmp/tmpfile
        echo "list_number_$i  $amod  $amod  $amod  90  90  90" >> /tmp/tmpfile
        cat list_${i} >> /tmp/tmpfile
        cp -rf list_${i}.txt list_${i}.txt.bak
        cp -rf /tmp/tmpfile list_${i}.txt
done

What on earth are you doing trying to use shell plus sed plus bc for this??? The general purpose UNIX text manipulation tool is awk:

awk 'BEGIN {
    a_original_A = 5
    split("0.88 0.90 0.92 0.94 0.96 0.98 1.00 1.02 1.04 1.06 1.08 1.10 1.12",nums)
    for (i in nums) {
        num = nums[i]
        out = "list_" num ".txt"
        amod = num * a_original_A
        print "12" > out
        print "list_number_" num, amod, amod, amod, 90, 90, 90" > out
        close(out)
    }
}'

wrt your comment below, if you already have files in your directory then with GNU awk (which I assume you have since you're using GNU sed in your example) it'd be:

awk -i inplace '
BEGIN { a_original_A = 5 }
FNR==1 {
    num = gensub(/.*_/,"",1,FILENAME)
    amod = num * a_original_A
    print "12"
    print "list_number_" num, amod, amod, amod, 90, 90, 90"
}
{ print }
' list_*.txt

There are many possible ways to do this. This code uses the seq command to generate the range of numbers. It comes in 3 parts. The first part creates the 'pre-existing' files.

The second part shows two ways of editing the files. The version with the line (tag) 12A doesn't require support for -i from sed (it isn't standard, and the behaviour of GNU sed is different from the behaviour of BSD (Mac OS X) sed ). The version with the line (tag) 12B uses classical sed notation (which works with both GNU sed and other variants) to insert two lines of information before line 1 of the original text in the file.

# Generate 'pre-existing' files
for number in $(seq -f '%4.2f' 0.88 0.02 1.12)
do echo "Pre-existing data in file $number" > list_$number.txt
done

tmp=$(mktemp ./tmp.XXXXXX)
trap "rm -f $tmp; exit 1" 0 1 2 3 13 15

for number in $(seq -f '%4.2f' 0.88 0.02 1.12)
do
    list="list_$number.txt"

    # Works without using sed
    {
    echo "12A"
    echo "$number" | awk '{ x=5*$1; printf("list_number_%4.2f %4.1f %4.1f %4.1f 90 90 90\n", $1, x, x, x) }'
    cat "$list"
    } > "$tmp"
    cp "$tmp" "$list"
    rm -f "$tmp"

    # Option 2 (as written, works with GNU sed and BSD sed)
    amod=$(echo "$number" | awk '{printf "%4.1f\n", 5*$1}')
    sed -i.bak -e "1i\\
    12B\\
    list_number_$number $amod $amod $amod 90 90 90" "$list"

done

trap 0 1 2 3 13 15

Sample output ( cat list_1.1?.txt ):

12B
list_number_1.10  5.5  5.5  5.5 90 90 90
12A
list_number_1.10  5.5  5.5  5.5 90 90 90
Pre-existing data in file 1.10
12B
list_number_1.12  5.6  5.6  5.6 90 90 90
12A
list_number_1.12  5.6  5.6  5.6 90 90 90
Pre-existing data in file 1.12

Obviously, the code assumes you have seq , but it is available as part of GNU CoreUtils and on Mac OS X.

Another technique altogether:

# Generate pre-existing files as before
for number in $(seq -f '%4.2f' 0.88 0.02 1.12)
do echo "Pre-existing data in file $number" > list_$number.txt
done

# Generate the two parameters from awk; use sed to edit each file in turn.
awk 'BEGIN { for (i = 0.88; i <= 1.12; i += 0.02) printf "%4.2f %4.1f\n", i, 5*i }' |
while read number amod
do
    list="list_$number.txt"
    sed -i.bak -e "1i\\
    12\\
    list_number_$number $amod $amod $amod 90 90 90" "$list"
done

Sample output ( cat list_1.1?.txt ):

12
list_number_1.10 5.5 5.5 5.5 90 90 90
Pre-existing data in file 1.10
12
list_number_1.12 5.6 5.6 5.6 90 90 90
Pre-existing data in file 1.12

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