0

I am trying to replace every instance of a block of six rows with another block of six rows, just reducing the six rows block of two columns to a six rows block of only one column.

Thank you to your comments I'll write this question more clearly. I have several guitar tablature text files each with many "lines" of music. Each "line" of music has 6 (as the guitar number of strings) consecutive rows of text. Between the "lines" of music there are empty (or with some text) lines. Normally these six row "lines" are about two hundred columns length, and I want to reduce the length of the lines by replacing each six vertical row of -- by a six vertical row of -.

As an example. I would like to reduce the first chunk to the second.

|------------------|    |-------|            
|------------------|    |-------|    
|-0----------------|    |-0-----|   
|-2-----2-----2----|    |-2-2-2-|     
|-------2----------|    |---2---|       
|-------------0----|    |-----0-| 

I have tried the following code (seen on unix.stackexchange 1) without success:

sed -i '/--/,/--/,/--/,/--/,/--/,/--/c\
-\
-\
-\
-\
-\
-' a.txt

I have had no better results with awk or vim or perl.

A partial solution, for example using awk with Field Separator empy, would be: find two consecutive columns all whose characters are either empty or "-". Then delete one of the two columns. But I do not know how to do it.

  • 2
    You mention in your first sentence that the file may have several columns, and that what you show is just one column out of many. Is that so? – Kusalananda Mar 10 at 19:29
  • 2
    Is that lines consisting literally of the two letters x and two backslashes? I'm not sure how that is two columns, can you edit the question to clarify? And if it's not literally xx<backslash><backslash>, can you add an example of what the data actually would be? – ilkkachu Mar 10 at 20:08
  • KIndly post expected ouput – Praveen Kumar BS Mar 11 at 20:48
  • Thank you for your comments. @Kusalananda: Yes, it is so.@ilkkachu: I have edited the question: it wasn't clear. Copying the chunk of "-" and "0" and "2" to a text editor with fixed length font, I think it is more clear what I would like to achieve. – ocap Mar 12 at 16:49
  • @ocap, hmm, that particular tablature seems to be based on parts like -x----, where x is either the number of the fret or another -. Removing some of the dashes from that would be simple, one could do that by just looking at one line at a time. But the problems come if the same file contains tablatures with different spacings (different numbers of dashes between the notes). Especially since we can't tell from the first line how many time units there are... – ilkkachu Mar 12 at 19:16
1

The tablature you posted seems to be built on six-character long pieces, -x----, where x is either a fret number or a dash. Like so:

 123456123456123456
 -x-----x-----x----
|------------------|
|------------------|
|-0----------------|
|-2-----2-----2----|
|-------2----------|
|-------------0----|

If they're all with that spacing, you can just simply change the pieces to remove some dashes, without regard for other lines.

$ sed -Ee 's/-(.)----/-\1/g; s/\|/-|/2' < tab
|-------| 
|-------|
|-0-----|
|-2-2-2-|
|---2---|
|-----0-|

But if you have tabs written with different spacings in the same file, then it gets much harder, as we'd need to recognize the spacing for each tab, and in general, that can't even be done from the first line. (since it can be empty as in your example.)

The solutions I can come up with for the more general case involve decoding the whole tablature and then reprinting it and that won't fit in this answer.


Note that sed's /this/,/that/ syntax processes blocks of lines where the first line matches /this/, the last line matches /that/, and the block contains all lines in between. /--/,/--/,/--/,... is therefore nonsense, since there are more patterns than just the start and end of a block.

To match a block that looks like a tablature, you'd need to match the |- and then have the block extend for six lines. In GNU sed, you could use /^|-/,+6 for that.

  • Thank you ilkkachu. It does not work because my question was poorly written. I have rewritten again. – ocap Mar 12 at 19:04
  • Thank you ilkkachu. I'll work all your advise to see if I find a solution. I have edited the question with a partial solution, that maybe could be implemented with awk. – ocap Mar 13 at 8:09
0

I have done by below method

command

i=`awk '{print NR}' l.txt | sort -nr | sed -n '1p'`

 for ((j=1;j<=$i;j++)); do sed -n ''$j'p' filename|awk -F "" '{gsub("","\n",$0);print $0}'|sort | uniq;done| sed '/^$/d'| sed "N;s/\n/ /g"| awk '{print $NF,$1}'| sed -r "s/ //g"

output

x\
x\
x\
x\
x\
x\
  • Thank you Praveen Kumar BS. I do not understand all this code; I am a novice, but should this code be inside a bash script? Because I get an error in the "i=..." part when I run it from the command line. – ocap Mar 13 at 8:13

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.