Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

Here is what I have

This
is
a
sample
text

How
to
do
it
?

I need the output to be:

This is a sample text
How to do it ?

In addition, how can I achieve the same with:

This
is
a
sample
text
How
to
do
it
?

How to append lines starting with non upper case characters to be appended each to previous line?

share|improve this question
add comment

5 Answers 5

up vote 3 down vote accepted
sed -r ':a;N;$!ba;s/\n([^A-Z])/ \1/g'

:a create a label b

N Search all the lines mashed together instead of searching line by line

$! if not the last line, b branch (go to) label a (skip the last line because the last line has a final newline)

s substitution

\n\([^A-Z]\) match a newline followed by anything not a capitalized letter. The ( and ) group together the anything not a capitalized letter.

/ \1/' replace our match with a space followed by group 1

g copy the hold buffer contents to the pattern space

Credit belongs here and here and here.

share|improve this answer
1  
Can you elaborate on how this works? –  Seth Mar 8 '13 at 18:12
    
Ok. working on it. –  Grimtech Mar 8 '13 at 18:15
    
Error: sed: -e expression #1, char 28: invalid reference \1 on `s' command's RHS –  Mina Mohsen Mar 8 '13 at 18:15
1  
@Mina let met help Grimtech a little while he Googles up his explanation :-): his incantation uses extended regular expressions, otherwise his capturing parentheses would have needed backslash escaping. So sed must be invoked with -r. –  zwets Mar 8 '13 at 18:44
    
Indeed. Thanks zwets. –  Grimtech Mar 8 '13 at 18:55
show 3 more comments

Considering that some sentences may include Capitalized words as well, perhaps this might be the solution you're looking for:

sed -n '
1h
1!H
$ {
        g
        s/\n\n/<br>/g
        p
}
' | \
sed -n '
1h
1!H
$ {
        g
        s/\n/ /g
        p
}
' | \
sed -e 's/<br>/\n/g'
share|improve this answer
    
It works. But I have a problem, In my actual file, there is no space between both sentences, so the output cames in one line! any help ? –  Mina Mohsen Mar 8 '13 at 17:54
add comment

bash builtins is the quickest way :-)

declare -a A
mapfile -t A <inputFile
for line in "${A[@]}"
do
  if [ -n "${line}" ]
  then
     if [ "${line}" = "${line^}" ]
     then
         echo -en "\n${line} "
     else
         echo -n "${line} "
     fi      
 else 
    echo "" # newline, because input line was empty
  fi
done   
share|improve this answer
    
I have a problem, In my actual file, there is no space between both sentences, so the output cames in one line! any help ? –  Mina Mohsen Mar 8 '13 at 17:52
    
@MinaMohsen: I have updated my answer. But please doesn't change the requirements in a question. Ask a new question instead. –  H.-Dirk Schmitt Mar 8 '13 at 18:49
    
I think this doesn't apply on special characters, I mean the '?'. Ok, I will next time. –  Mina Mohsen Mar 8 '13 at 18:57
add comment

How about a bash one-liner?

while read L; do case $L in [A-Z]*) echo ;; esac; echo -n "$L "; done; echo
share|improve this answer
    
Some lower case letters still exists at the beginning of some lines, dont know why! –  Mina Mohsen Mar 8 '13 at 18:55
    
@MinaMohsen Can you show me where this happens? I can't reproduce that. Your two examples above come out fine. –  zwets Mar 8 '13 at 19:14
    
Thanks zwets, Grimtech's solution worked perfectly. –  Mina Mohsen Mar 8 '13 at 19:23
add comment

With the first sample:

awk '{$1=$1}1' RS= file

with the second sample:

awk '/^[[:upper:]]/{print x}1' file | awk '{$1=$1}1' RS=
share|improve this answer
add comment

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.