OK, first of all do not use a for loop! That is very inefficient. Just give grep all the file names at once:
grep 'sometext:' folder/*.txt
In this case, however, I would use awk instead of grep. I made 10 copies of your input file to test:
$ awk '{
if($1~/sometext|someothertext|somedifferenttext/){
printf "%s,",$2
}
if(FNR==1 && NR>1){
print ""
}
}
END{ print "" }' folder/*txt
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Explanation
awk is a scripting language that reads its input line by line and splits each line on whitespace (by default, you can change that with -F) into fields. The first field will be $1, the second $2 etc.
if($1~/sometext|someothertext|somedifferenttext/){ : if the first field matches sometext or someothertext or somedifferenttext. Note that this will also match foosometext. If you want to limit to exact matches, change this to:
if($1=="sometext:" || $1=="someothertext:" || $1=="somedifferenttext:"){
printf "%s,",$2 : if the condition above is met, print the 2nd field followed by a comma.
if(FNR==1 && NR>1){ print "" } : NR is the current input line number and FNR is the current file's line number. So, print a newline (awk's print call adds a newline by default, so printing nothing is like printing a newline) each time the file's line number is 1 but not if the total number of lines processed is also one. In other words, print a newline each time we start reading a new file.
END{ print "" }' : also print a newline after processing all files.
Note that this assumes you only have 2 fields per line. If you need to print the entire line instead, you can use (using the version that only prints exact matches to illustrate):
awk '{
if($1=="sometext:" ||
$1=="someothertext:" ||
$1=="somedifferenttext:"){
$1="";
printf "%s,",$0
}
if(FNR==1 && NR>1){print ""}
}END{print ""}' folder/*txt | sed 's/^ //'
The difference is that we use $0 (the full line) instead of $2 and set $1 to the empty string before printing. This results in an extra space printed at the beginning (because the empty $1 is still considered a field), so we pass that through sed to remove it.
Alternatively, you could also do the whole thing in Perl:
$ perl -lane '
if($F[0]=~/(sometext|someothertext|somedifferenttext):/){
push @k,@F[1..$#F]
}
if(eof){
print join ",", @k; @k=();
}' folder/file*
Hello,World,!
Hello,World,!
Hello,World,!
Hello,World,!
Hello,World,!
Hello,World,!
Hello,World,!
Hello,World,!
Hello,World,!
Hello,World,!
Hello,World,!
Or, to also have the trailing ,:
$ perl -lane '
if($F[0]=~/^(sometext|someothertext|somedifferenttext):$/){
push @k,@F[1..$#F]
}
if(eof){
print join ",", @k , ""; @k=();
}' folder/file*
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Explanation
The basic idea here is the same. Perl's -a switch makes it behave like awk, splitting each input line into the array @F. Then, if the 1st element of the array is one of the desired strings, the rest of the fields (@F[1..$#F]) are is added to the array @k. If we reach the end of a file (if(eof)), we join the contents of the @k array with commas and print the resulting string.
Finally, here's one way to do it in the way you were attempting (assuming GNU grep):
$ for f in folder/*; do
grep -hoP '^(sometext|someothertext|somedifferenttext): \K.*' "$f" |
perl -pe 's/\n/,/; END{print "\n"}';
done
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
Hello,World,!,
sometextalso match theWorldand!lines?sed '/some.*:/{s/.*: //;H};$!d;x;s/\n//;s/\n/,/g' "$FILE"\nwith,.