3

I have a file looking like the following:

abcdefghijklmnopqrst
//
abcdefghijklmnopqrst
//
abcdefghijklmnopqrst

I use the following code to insert a line with // to the beginning of the document (as advised here: Adding text to beginning of text file), and save this update to a new file.

sed '1s/^/\/\/\'$'\n/' File_1.txt > File_2.txt

What I would like to do, however, is to add unique names after each //, getting a result like this:

// Text 1
abcdefghijklmnopqrst
// Text 2
abcdefghijklmnopqrst
// Text 3
abcdefghijklmnopqrst

etc.

I was thinking I could use tr to translate eg. "//" into "// Text 1". But how do I add Text 2 to the next //, text 3 to the third // etc.? The txt file is mac-osx made.

UPDATE:

Your solution looks good, @PM 2Ring, however, I have the addiditional problem, that the file actually looks like this:

// 
abcdefghijklmnopqrstu 
//            x   x 
abcdefghijklmnopqrstu 
//          x   x 
abcdefghijklmnopqrstu 

So the name is perfectly inserted in first line, but after the secons pair of /, the name is inserted after x, at the end of the line. I need to insert the name just after //, but without shifting the remaining text to the right. Is it possible to delete the same amount of spaces, as the there are characters in the name? This should then not be done in the first line, of course, as I assume this would delete characters from the second line.

  • 1
    The question is: Where do these unique texts come from? Counting would be easy. – Hauke Laging Jan 28 '15 at 11:08
1

You can easily do this with awk:

awk 'BEGIN{n=1}; /\/\//{$0=$0 " Text " n; n+=1}; {print}' infile

If infile contains

//
abcdefghijklmnopqrst
//
abcdefghijklmnopqrst
//
abcdefghijklmnopqrst

The above command prints

// Text 1
abcdefghijklmnopqrst
// Text 2
abcdefghijklmnopqrst
// Text 3
abcdefghijklmnopqrst

The cryptic-looking /\/\// is a regex (a Regular Expression) containing //. In awk regexes are delimited by the forward slash /; to put forward slashes into a regex you need to escape them with the backslash \.

In awk, pattern{action} says perform action if the current line matches the pattern. The BEGIN pattern is a special pattern to signify actions we want to happen before any lines are read. If we don't specify a pattern, the action is performed for all lines (although there is a way to override that).


This updated version will sort-of work on your new input file, but unfortunately it won't preserve the spacing

awk 'BEGIN{n=1}; /^\/\//{$1=$1 " Text " n; n+=1}; {print}' infile

input

// x  x
abcdefghijklmnopqrst
//    x    x
abcdefghijklmnopqrst
//          x   x
abcdefghijklmnopqrst

output

// Text 1 x x
abcdefghijklmnopqrst
// Text 2 x x
abcdefghijklmnopqrst
// Text 3 x x
abcdefghijklmnopqrst
  • You can do n+=1 (or n++) before $0=... to exclude BEGIN{n=1} – Costas Jan 28 '15 at 11:55
  • @Costas: Good point, but I decided to use explicit initialisation of n to make it easier for people unfamiliar with awk to understand, and to make it easier for them to modify the starting number, if desired. – PM 2Ring Jan 28 '15 at 12:00
  • 1
    awk do not require variable pre-initializaton. And so as we try to use ideologicaly right patterns I'd like to offer {n++ ; $(NF+1)="Text" ; $(NF+1)=n} instead of your {$0=$0...} – Costas Jan 28 '15 at 12:12
  • @Hjalte Try to exchange $0 to $1 – Costas Jan 28 '15 at 12:27
  • This is what I am aiming at, thank you! I have some additional trouble, however. I have updated my question above. – Hjalte Jan 28 '15 at 12:27
1

You can use perl, and the evaluation flag to increment a variable in the replacement part. It search for every line that begins with // and appends Text followed by a number:

perl -pe 's{\A(//)}{$1 . " Text " . ++$i}e' File_1.txt

It yields:

// Text 1 
abcdefghijklmnopqrst
// Text 2 
abcdefghijklmnopqrst
// Text 3  
abcdefghijklmnopqrst

Update (see comments):

Do grouping on the spaces after // and calculate the number of spaces to insert in the replacement part, like:

perl -pe 's{\A(//)(\h*)}{$1 . " Text " . ++$i . " " x ((length ($2)) - length(" Text " . $i))}e' temp

Using your last example, it yields:

// Text 1
abcdefghijklmnopqrstu 
// Text 2     x   x 
abcdefghijklmnopqrstu 
// Text 3   x   x
abcdefghijklmnopqrstu
  • This works very good, thank you! Do you have an idea for a soloution for my updated problem above? Your solution inserts the unique name perfectly after //, but also shifts the remaing text to the right. Is it possible to avoid this? So delete as many spacings as characters inserted? – Hjalte Jan 28 '15 at 13:43
  • @Hjalte: I've updated my answer. – Birei Jan 28 '15 at 14:13
0

Converting @Birei solution to the "additional trouble" update:

perl -pe 's{^// {10}}{sprintf("// Text %-3d ",++$i)}e  or
          s{^//     }{sprintf("// Text %d",   ++$i)}ex '          infile

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.