0

Lets say that I have:

cat FILENAME1.txt
Definition john 
cat FILENAME2.txt
Definition mary
cat FILENAME3.txt
Definition gary

cat  textfile.edited
text
text 
text

I want to obtain an ouput like:

1 john text
2 mary text
3 gary text

I tried to use "stored" values from FILENAMES "generated" by a loop. I wrote this:

for file in $(ls *.txt); do


        name=$(cat $file| grep -i Definition|awk '{$1="";print $0}')
        #echo $name  --> this command works as it gives the names

done 

        cat textfile.edited|  awk  '{printf "%s\t%s\n",NR,$0}'

which very close to what I want to get

1   text
2   text 
3   text

My issue was coming through when I tried to add the "stored" value. I tried the following with no success.

cat textfile.edited|  awk  '{printf "%s\t%s\n",$name,NR,$0}' 

cat textfile.edited|  awk  '{printf "%s\t%s\n",name,NR,$0}'

cat textfile.edited|  awk -v name=$name '{printf "%s\t%s\n",NR,$0}' 

Sorry if the terminology used is not the best, but I started scripting recently. Thank you in advance!!!

KGee
  • 323
  • 1
  • 9
  • @oguzismail thnx for the answer. Unfortunately, this command prints the same output as cat textfile.edited| awk '{printf "%s\t%s\n",NR,$0}' having tab delimiter at the beginning – KGee Aug 10 '20 at 09:50
  • 3
    `for file in $(ls *.txt);` is better written as `for file in *.txt;`, btw. See https://mywiki.wooledge.org/ParsingLs – Shawn Aug 10 '20 at 09:50
  • Are you always going to have the same number of FILENAMEx.txt files as lines in the textfile.edited one? – Shawn Aug 10 '20 at 09:52
  • @Shawn .Thanks for the link/suggestion!.... No the lines are not the same as the number of files. – KGee Aug 10 '20 at 10:03
  • @KGee: So you need to explain what to do, if they don't match – Inian Aug 10 '20 at 10:13
  • @Shawn ops!! Sorry I would like to wrote "the No the lines are the same as the number of files.... – KGee Aug 10 '20 at 10:19
  • @Inian ... i did a mistake in my previous post with Shawn .... thanx for telling me. – KGee Aug 10 '20 at 10:20
  • 2
    wish this could be sticky somewhere, could post that in nearly every second comment [Filenames and Pathnames in Shell: How to do it Correctly, David A. Wheeler](https://stackoverflow.com/a/37210472) – alecxs Aug 10 '20 at 11:05

4 Answers4

3

One solution using paste and awk ...

We'll append a count to the lines in textfile.edited (so we can see which lines are matched by paste):

$ cat textfile.edited
text1
text2
text3

First we'll look at the paste component:

$ paste <(egrep -hi Definition FILENAME*.txt) textfile.edited
Definition john text1
Definition mary text2
Definition gary text3

From here awk can do the final slicing-n-dicing-n-numbering:

$ paste <(egrep -hi Definition FILENAME*.txt) textfile.edited | awk 'BEGIN {OFS="\t"} {print NR,$2,$3}'
1       john    text1
2       mary    text2
3       gary    text3

NOTE: It's not clear (to me) if the requirement is for a space or tab between the 2nd and 3rd columns; above solution assumes a tab, while using a space would be doable via a (awk) printf call.

markp-fuso
  • 28,790
  • 4
  • 16
  • 36
  • Works perfectly!!! thanks a lot. In this way I will avoid messing with stored values – KGee Aug 10 '20 at 13:51
1

You can do all with one awk command.
First file is the textfile.edited, other files are mentioned last.

awk 'NR==FNR {text[NR]=$0;next}
     /^Definition/ {namenr++; names[namenr]=$2}
     END { for (i=1;i<=namenr;i++) printf("%s %s %s\n", i, names[i], text[i]);}
     ' textfile.edited FILENAME*.txt

You can avoid awk with

paste -d' ' <(seq $(wc -l <textfile.edited)) \
            <(sed -n 's/^Definition //p' FILE*) \
            textfile.edited
Walter A
  • 19,067
  • 2
  • 23
  • 43
  • Thanks a lot for your response. I tested it and works. The only reason why accept another answer was that your way was a bit complicated for my level. – KGee Aug 10 '20 at 13:53
1

A one-liner using GNU utilities:

paste -d ' ' <(cat -n FILENAME*.txt | sed 's/\sDefinition//') textfile.edited

Or,

paste -d ' ' <(cat -n FILENAME*.txt | sed 's/^\s*//;s/\sDefinition//') textfile.edited

if the leading white spaces are not desired.


Alternatively:

paste -d ' ' <(sed 's/^Definition\s//' FILENAME*.txt | cat -n) textfile.edited
M. Nejat Aydin
  • 9,597
  • 1
  • 7
  • 17
  • Thank you so much for your answers!!! You indicated another way of dealing with paste and sed... Im surprised!!! The only reason why I accepted markp-fusos' answer over yours was only that he posted first! Both ways were understandable for a "new kid on the block" like me – KGee Aug 10 '20 at 13:58
1

Another version of the paste solution with a slightly careless grep -

$: paste -d\  <( grep -ho '[^ ]*$' FILENAME?.txt ) textfile.edited
john text
mary text
gary text

Or, one more way to look at it...

$: a=( $(sed '/^Definition /s/.* //;' FILENAME[123].txt) )
$: echo "${a[@]}"
john mary gary

$: b=( $(<textfile.edited) )
$: echo "${b[@]}"
text text text

$: c=-1 # initialize so that the first pre-increment returns 0
$: while [[ -n "${a[++c]}" ]]; do echo "${a[c]} ${b[c]}"; done
john text
mary text
gary text

This will put all the values in memory before printing anything, so if the lists are really large it might not be your best bet. If they are fairly small, it's pretty efficient, and a single parallel index will keep them in order.

If the lines are not the same as the number of files, what did you want to do? As long as there aren't more files than lines, and any extra lines are ok to ignore, this still works. If there are more files than lines, then we need to know how you'd prefer to handle that.

Paul Hodges
  • 13,382
  • 1
  • 17
  • 36
  • Thank you very much... The second way was a bit complicated for my level... But I will keep the " while" way for the future... Im not confident to deal with storing values but in a way I have to learn to do so! – KGee Aug 10 '20 at 14:02
  • 1
    Worth practicing. Arrays are a great tool. ;) Good, luck, and have fun! – Paul Hodges Aug 10 '20 at 14:14