问题描述:

I'm writing a bash script that would allow me to take a certain amount of text from a file and add some other text before that for a list of files.

directory=$(pwd)

for f in *test.txt

do

filename=$(basename $f .txt)

printf "%%sum=4 \n"> input.temp

printf "file=$directory"/"$filename".txt" \n">> input.temp

printf "some commands \n">> input.temp

printf "\n" >> input.temp

printf "description \n">> input.temp

sed -n "/0 1/,$p" "$f" >> input.temp;

mv input.temp $filename.temp

done

I have a problem with the sed command inside the for loop. I looked around and people suggest adding double quotes which I did but to no avail. I think it might be the $p.

I hope this is clear enough. If it's not, I'll try to explain better.

sed -n "/0 1/,$p" "$f" >> input.temp; does not work

sed -n '/0 1/,$p' "$f" >> input.temp; does not work

sed -n "/0 1/,\$p" "$f" >> input.temp; does not work

FYI I'm not trying to find something else that works. I want to fix this exact input. I sound like an asshole I'm sure.

Sample input

%sum=8

file=otherpath/filename.txt

some other commands

another description

0 1

0.36920852 -0.56246512

0.77541848 0.05756533

2.05409026 0.62333039

2.92655258 0.56906375

2.52034254 -0.05096652

1.24167014 -0.61673008

-0.60708600 -0.99443872

0.10927459 0.09899803

3.90284624 1.00103940

3.18648588 -0.09239788

0.93151968 -1.09013674

2.50047427 1.30468389

2.19361322 2.54108378

3.18742399 0.34152442

3.38679424 1.11276220

1.56936488 3.27250306

1.81754180 4.19564055

1 2 1.5 6

2 3 1.5

3 4

4 5 1.5

5 6 1.5

6 11 1.0

7

8

9

10

11

12

13 16

14

15

16 17

17

My desired output is basically this file from "0 1" till the end preceded by the stuff I put inside the printf.

UPDATE: If you're interested, the two scripts tripleee and Ed Morton provided work perfectly well. The problem in my script was me leaving out the -i option from the sed line (for inplace).

sed -n "/0 1/,$p" "$f" >> input.temp

should be replaced by

sed -ni '/0 1/,$p' "$f"

网友答案:

I see you updated your question and provided some additional information in your comments so try this, uses GNU awk 4.* for -i inplace:

awk -i inplace -v directory="$(pwd)" '
FNR==1 {
    print "%%sum=4 "
    print "file=" directory "/" FILENAME
    print "some commands "
    print ""
    print "description "
    found = 0
}
/0 1/ { found = 1 }
found
' *text.txt

If you don't have GNU awk then the technically correct way to do it is using xargs but it's simpler using a shell loop for the file manipulation (moving) part:

for file in *test.txt
do
    awk -v directory="$(pwd)" '
    FNR==1 {
        print "%%sum=4 "
        print "file=" directory "/" FILENAME
        print "some commands "
        print ""
        print "description "
        found = 0
    }
    /0 1/ { found = 1 }
    found
    ' "$file" > tmp && mv tmp "$file"
done
网友答案:

Like others have already commented, you basically just need to use single quotes instead of double, because $p in double quotes gets replaced with the value of the shell variable p by the shell, before sed executes (in practice, probably an empty string).

However, you might also want to investigate doing it all in sed. You might then instead stick with the double quotes (because there are other variables you do want to substitute) and instead escape the dollar sign in $p with a backslash to protect it from the shell.

directory=$(pwd)   # just do this once before the loop; the value doesn't change
for f in *text.txt; do
    # no braces
    filename=$(basename "$f" .txt)
    sed -n "1i\\
%sum=4\\
file=$directory/$filename.txt\\
some commands\\
\\
description
        /0 1/,\$p" "$f" >inputout.temp2  # no pointless separate temp file
done

In practice, I imagine you would like for the output file to be different in each iteration (maybe "$filename.temp" instead?) but what you do about that is up to you, obviously. As it is now, the file will contain the output from the last iteration.

相关阅读:
Top