Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Ok, since this is a complex question, I will explain it clearly. I got a file content shown as below:

$ Cat File1 
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {TBMKF}
ABC Cool Lol POP {YUKER}
ABC Cool Lol POP {EFEFVD}

The output that I want

-Cool MNB +  POP ;
-Cool MNB  + POP ;
-Cool MNB  + POP ;
-Cool TBMKF + POP ;
-Cool YUKER + POP ;
-Cool EFEFVD +POP ;

Firstly I try to take out the last column from the File1 and print it out by sed 's/[{}//g' File1 > File3

After that I copy the whole content of File1 to a new File4

cp File1 File4

After that I replace the data inside the File4 with the File3 data (means the data without bracket one "File1 last column that one")

awk 'FNR==NR{a[NR]=$1;next}{$5=a[FNR]}1' File3 File4 >>File5 

Output should be like this

ABC Cool Lol POP MNB
ABC Cool Lol POP MNB
ABC Cool Lol POP MNB
ABC Cool Lol POP TBMKF
ABC Cool Lol POP YUKER
ABC Cool Lol POP EFEFVD

Finally, I try

awk -F“ " '{print - $2,$5 +,$4 ";"}‘ File5

But the outcome did not come out as shown as I want, only the similar data MNB is all listed down, others did not shown up (File one last column data), I not sure what is wrong, hope everyone can help me if you know and can guide me with a more nicely way. My way for doing this is quite long winded.

share|improve this question
    
Are you using gnu awk? – 123 yesterday
    
i not sure what u mean .But I just a new begineer for touching awk .This is the task that I need to be done ,I try my best to slowly one step to one step to do that based on my understanding of awk. – heng960407 yesterday
1  
type awk --version, whats the result? – 123 yesterday
2  
Please change your title to something more specific to your problem. This will make it easier for others who have similar questions in future to find it. At the moment "A question about awk" is very general. – Tom Fenech 15 hours ago
up vote 15 down vote accepted

I don't know why you are copying things left and right. The simple thing is

awk '{print "-" $2, substr($5,2,length($5)-2), "+", $4, ";"}' File1

I put the - in the beginning and the ; at then end.

In between we print

  • $2 because we want it as it is.
  • a substring of $5, which is the string without the first and the last character. We skip the first character by starting at position 2 (awk has always been strange about that) and leave out the last character by only selecting a substring which is two characters shorter, than the original $5
  • the + because we want it
  • and then $4

However, I'm not sure if all these string functions are specific to GNU awk.

share|improve this answer
    
substr(string, 2) returns the substring starting from the second character, like cut -c2-, tail -n +2, sed '2,$'... What's so strange about that? – Stéphane Chazelas yesterday
    
thank you, I will try – heng960407 yesterday
2  
That command is standard and would even work with the original awk from the 70s. – Stéphane Chazelas yesterday
    
@StéphaneChazelas: Ah, I've been waiting for you :-) Usually we start counting at 0 which means index 2 is the third position, but here the second position is at index 2. Thanks for clarifying the remaining GNU question. – Bananguin yesterday
    
@Bananguin, in Unix shell and utilities as shown in the few examples above, we start at 1, not 0. Most notable exceptions are ksh's arrays and ${var:offset} (both copied by bash). All other shell arrays start at 1. See also Is there a reason why the first element of a Zsh array is indexed by 1 instead of 0? – Stéphane Chazelas yesterday

With sed

sed '
    s/\S\+\s/-/
    s/\(\S\+\s\)\{2\}{\(\S\+\)}/\2 + \1;/
    ' File1

And awk variation

awk -F"[[:blank:]{}]+" '{print "-" $2, $5, "+", $4}' ORS=" ;\n" File1
share|improve this answer

Easy TXR job:

$ txr -c '@(repeat)
@a @b @c @d {@e}
@(do (put-line `-@b @e + @d ;`))
@(end)' -
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {TBMKF}
ABC Cool Lol POP {YUKER}
ABC Cool Lol POP {EFEFVD}
[Ctrl-D][Enter]
-Cool MNB + POP ;
-Cool MNB + POP ;
-Cool MNB + POP ;
-Cool TBMKF + POP ;
-Cool YUKER + POP ;
-Cool EFEFVD + POP ;

Using TXR Lisp awk macro to transliterate Awk solution:

 txr -e '(awk (t (prn `-@[f 1] @{[f 4] [1..-1]} + @[f 3] ;`)))'

Fields are in the f list, and indexing is zero based.

share|improve this answer
1  
+1 for the lisp and crytiest look ! That language MUST compete in pcg ( programming code golf) – Archemar yesterday
    
@Archemar TXR doesn't compete in golfing very well because there are specialized languages designed for that which do things like assign functions to individual characters, which can then be strung together to achieve composition. – Kaz yesterday
    

Using awk is easiest when the $1,$2,... fields already contain the exact strings you want to work with. The field separator, if it contains more than one character, is interpreted as a regular expression. We don't need to do any search and replace or substring operations to get rid of the {curly braces}. We just count them as part of the delimiter.

awk -F'[ {}]+' '{printf("-%s %s + %s ;\n", $2, $5, $4)}'

Using printf instead of print also makes it a bit easier to see how the string will be formatted, but if you want to have print "-"$2,$5" + "$4";" instead of printf("-%s %s + %s ;\n", $2, $5, $4), that's an option.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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