0

I have a list of files in bash - file1.txt, file2.txt, file3.txt and I would like to make another list that include this strings without .txt, so

names2 = (file1, file2, file3)

Then, I would like to find these strings in a file and add a before this strings. How to do that please?

My Code:

names = (file1.txt, file2.txt, file3.txt)

for i in "${names[@]}"; do
    awk '{ gsub("$i","a-$i") }' f.txt > g.txt

f.txt:

TEXT
\connect{file1}
\begin{file2}
\connect{file3}
TEXT 
75

Desired output g.txt

TEXT
\connect{a-file1}
\begin{a-file2}
\connect{a-file3}
TEXT 
75
4
  • You can not use $i directly in awk, read this on how to use variables with awk stackoverflow.com/questions/19075671/… Commented Nov 1, 2019 at 5:53
  • 1
    names2 = (file1, file2, file3) is not a valid declaration of an array. There are no spaces in bash assignments. names=(file1.txt, file2.txt, file3.txt) is the right approach Commented Nov 1, 2019 at 5:53
  • Add a shebang and then paste your script there: shellcheck.net Commented Nov 1, 2019 at 6:05
  • There's no reason to put the strings in an array if you only use the array once. Just say for i in file1 file2 file3; do ... Commented Nov 1, 2019 at 10:13

2 Answers 2

2

With sed+printf:

$ names=(file1 file2 file3) # Declare array

$ printf 's/%s/a-&/g\n' "${names[@]}" # Generate sed replacement script
s/file1/a-&/g
s/file2/a-&/g
s/file3/a-&/g

$ sed -f <(printf 's/%s/a-&/g\n' "${names[@]}") f.txt
TEXT
\connect{a-file1}
\begin{a-file2}
\connect{a-file3}
TEXT
75

If your array contains .txt suffix, use this:

$ names=(file1.txt file2.txt file3.txt) # Declare array

$ printf 's/%s/a-&/g\n' "${names[@]%.txt}" # Generate sed replacement script
s/file1/a-&/g
s/file2/a-&/g
s/file3/a-&/g

$ sed -f <(printf 's/%s/a-&/g\n' "${names[@]%.txt}") f.txt
TEXT
\connect{a-file1}
\begin{a-file2}
\connect{a-file3}
TEXT
75

If the files list contains the names which have overlapping string, you can use the word boundaries (\<,\>) to handle this. e.g.

$ cat f.txt
TEXT
\connect{file1}
\begin{file2}
\connect{file3file2}
TEXT 
75

$ names=(file1.txt file2.txt file3file2.txt) # Declare array
$ printf 's/\<%s\>/a-&/g\n' "${names[@]%.txt}" # Generate sed replacement script
s/\<file1\>/a-&/g
s/\<file2\>/a-&/g
s/\<file3file2\>/a-&/g

$ sed -f <(printf 's/\<%s\>/a-&/g\n' "${names[@]%.txt}") f.txt
TEXT
\connect{a-file1}
\begin{a-file2}
\connect{a-file3file2}
TEXT 
75
Sign up to request clarification or add additional context in comments.

2 Comments

How to make conditions that solve the following problem please? names=(file1.txt file2.txt file3file2.txt) I mean that there is a world in the names of files that is repeated as a part of another name of file. Then there is added a- more times.
You could use word boundaries (\<, \>). printf 's/\<%s\>/a-&/g\n' "${names[@]%.txt}"
2

Could you please try following.

Variable with values in shell:

string="file1.txt, file2.txt, file3.txt"

Creating a shell array as follows:

IFS=', ' read -r -a array <<< "$string"

OR if you want to stick with your way of defining array then do like:

array=(file1.txt file2.txt file3.txt)

Passing above shell created array to awk and reading Input_file for doing the final operations.

awk -v arr="${array[*]}" '
BEGIN{
  FS=OFS="{"
  num=split(arr,array," ")
  for(i=1;i<=num;i++){
    sub(/\.txt/,"",array[i])
    array1[array[i]"}"]
  }
}
$2 in array1{
  $2="a-"$2
}
1
'  Input_file

Explanation: Adding explanation of above code here.

awk -v arr="${array[*]}" '       ##Creating a variable named arr whose value is all elements of array(shell array).
BEGIN{                           ##Starting BEGIN section of awk code here.
  FS=OFS="{"                     ##Setting FS and OFS as { here.
  num=split(arr,array," ")       ##Splitting arr variable into array named array with delimiter space and its length is stored in num variable.
  for(i=1;i<=num;i++){           ##Starting for loop from i=1 to till value of variable num.
    sub(/\.txt/,"",array[i])     ##Using sub to substitute .txt with NULL in array value whose index is variable named i.
    array1[array[i]"}"]          ##Creating an array1 whose index is array[i] value with } in it.
  }                              ##Closing for loop here.
}                                ##Closing BEGIN section of code here.
$2 in array1{                    ##Checking condition if $2 of current line is present in array named array1 then do following.
  $2="a-"$2                      ##Adding string a- with value of $2.
}                                ##Closing BLOCK for condition here.
1                                ##Mentioning 1 will print edited/non-edited line of Input_file.
'  Input_file                    ##Mentioning Input_file name here.

11 Comments

Thank you very much. And how to create string="file1, file2, file3" when I have in my code: names = (file1.txt, file2.txt, file3.txt) ?
Didn't you read the comment I posted in the question? The array declaration as names = (file1.txt, file2.txt, file3.txt) is simply wrong!
@Archie, I have changed my code now, where array's values are having .txt in it and how it will handle them in awk code too, lemme know if this helps you now?
Thank you very much, it works. Could you please explain to me the last part please?
Thank you very much
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.