3

What shell script should I use in Linux to replace a group with n lines of text with a single line?

I have a file like :

a
b
c
*
d
e
f
*
g
h
i
*

and I want to get a file as:

abc
def
ghi
3
  • Something like 'i=0; while read line; do test $((++i))', but I haven't found any solution Commented Jan 10, 2014 at 9:08
  • I just saw your answer stackoverflow.com/a/21042715/1983854 . Why don't you give proper input? All the approaches were based on your input which is very far from the one you are using in your answer. Commented Jan 10, 2014 at 11:17
  • 1
    @fedorqui and besides, his/her answer is the longest and least understandable of all :) Commented Jan 10, 2014 at 11:44

8 Answers 8

2

sed way:

sed ':a;N;$!ba;s/\n//g' < t | sed 's:*:\n:g'

t is the file you want to change.

references: How can I replace a newline (\n) using sed? Why does sed not replace all occurrences?

The first command replaces \n with nothing. the second replaces * with \n.

sed is a very powerful stream editor tool by the way, knowing it can help you in more ways than you can imagine.

Sign up to request clarification or add additional context in comments.

Comments

2

can use awk

awk '{if ($0=="*"){print s;s=""}else{s=s$0}}' file

an bash way to this is

while read x
do
   [ "$x" == "*" ] && echo  || echo -n $x
done < file

Comments

1

Other than awk solution :

tr '\n' ' ' < Input.txt |sed 's/ //g' | tr '*' '\n'

Comments

0

One awk way:

$ awk '/\*/ {printf "\n"; next} {printf $1}' file
abc
def
ghi
  • In case of *, print a new line. Otherwise, print the character. Using printf, so that new line is not added unless specified.

With xargs:

$ xargs -n4 < file | cut -d' ' -f1-3
a b c
d e f
g h i
  • xargs -n4 < file prints the file in blocks of 4 columns. cut -d' ' -f1-3 prints from 1st to 3rd column.

Comments

0

If you treat * as the line token, try remove '\n' and replace STAR.

cat <youfile> | tr -d '\n' | tr '*' '\n'

1 Comment

instead of using 2 pipes, you could have said tr -d '\n' < file | tr '*' '\n'
0

You can do it in the shell without awk, or tr, or anything external too:

#!/bin/bash
while read x
do
   if [ "$x" == "*" ]; then
      echo $line
      line=""
   else
      line="$line$x"
   fi
done

Save as "go", then do:

chmod +x go
./go <inputfile

Comments

0

I believe tr could be considered the correct tool to replace single characters.

tr -d '\n' < file | tr '*' '\n'

Correct in this context would mean most lightweight, least clumsy, least bug-prone, and least cognitively demanding for the purpose. The other solutions work, but tr has the least hidden costs. When you use a lot of small tools as you do in unix, these small advantages really add up over time.

Comments

0

Thanks to everybody, I've found this solution which works in case the file is like

field1     2008
field2     703
field3     qeew
field4     80
field5     52
field6     749.11

field1     2009
field2     532
field3     wecwer
field4     82
field5     44
field6     649.97

...

#!/bin/bash

if [ "$1" = "" ]
then
   echo "missing file name"
   exit 1
fi

N=7
i=0
FULL_ROW=""
SAVEIFS=$IFS
if [ -f $1 -a -r $1 ]; then
    LAST_DATA_SCAD=""
    while IFS=$(echo -en "|\n\b") read -ra ROW_RECORD; do

    if [[ "$FULL_ROW" == "" ]]
       then
        FULL_ROW=${ROW_RECORD:11}
       else
        FULL_ROW=$FULL_ROW"|"${ROW_RECORD:11}
    fi
    i=$((i+1))
    if [ $((10#$i)) == $N ]
    then
      echo $FULL_ROW
      FULL_ROW=""
      i=0
    fi
    done < "$1"
   else
     echo "file not found"
   fi
   IFS=$SAVEIFS

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.