Is it possible with Gedit or the command line to modify every fourth line of a text file?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP








up vote
11
down vote

favorite
3












I am trying to convert a text file into a tab separated spreadsheet. My text file is something like this:



Dog
Cat
Fish
Lizard
Wolf
Lion
Shark
Gecko
Coyote
Puma
Eel
Iguana


With standard search and replace functions in Gedit or LibreOffice, it's easyto replace the end of line with a tab. But if I just swap carriage returns for tabs, I'll get this:



Dog Cat Fish Lizard Wolf Lion Shark Gecko Coyote Puma Eel Iguana


But what I need to do is get it to look like this:



Dog Cat Fish Lizard
Wolf Lion Shark Gecko
Coyote Puma Eel Iguana


So, can I swap every end of line character for a tab except for every fourth line?



I don't know if that kind of conditional iteration can be done with regular expressions inside a program like Gedit or LibreOffice, so maybe this needs to be some kind of command line function? I'm not even clear on what the best tool to start with is.




Update:



I tried the following commands:



sed 'N;N;N;s/n/t/g' file > file.tsv

paste - - - - < file > file.tsv

pr -aT -s$'t' -4 file > file.tsv

xargs -d 'n' -n4 < inputfile.txt


But when I try to open the resulting tsv file in LibreOffice, the columns are not quite right. I'm not sure if this means I'm not executing the above commands correctly, or if I'm doing something wrong in the LibreOffice import function:



TSV opening in Calc



Just for reference, the desired result should look like this:



Proper columns







share|improve this question


























    up vote
    11
    down vote

    favorite
    3












    I am trying to convert a text file into a tab separated spreadsheet. My text file is something like this:



    Dog
    Cat
    Fish
    Lizard
    Wolf
    Lion
    Shark
    Gecko
    Coyote
    Puma
    Eel
    Iguana


    With standard search and replace functions in Gedit or LibreOffice, it's easyto replace the end of line with a tab. But if I just swap carriage returns for tabs, I'll get this:



    Dog Cat Fish Lizard Wolf Lion Shark Gecko Coyote Puma Eel Iguana


    But what I need to do is get it to look like this:



    Dog Cat Fish Lizard
    Wolf Lion Shark Gecko
    Coyote Puma Eel Iguana


    So, can I swap every end of line character for a tab except for every fourth line?



    I don't know if that kind of conditional iteration can be done with regular expressions inside a program like Gedit or LibreOffice, so maybe this needs to be some kind of command line function? I'm not even clear on what the best tool to start with is.




    Update:



    I tried the following commands:



    sed 'N;N;N;s/n/t/g' file > file.tsv

    paste - - - - < file > file.tsv

    pr -aT -s$'t' -4 file > file.tsv

    xargs -d 'n' -n4 < inputfile.txt


    But when I try to open the resulting tsv file in LibreOffice, the columns are not quite right. I'm not sure if this means I'm not executing the above commands correctly, or if I'm doing something wrong in the LibreOffice import function:



    TSV opening in Calc



    Just for reference, the desired result should look like this:



    Proper columns







    share|improve this question
























      up vote
      11
      down vote

      favorite
      3









      up vote
      11
      down vote

      favorite
      3






      3





      I am trying to convert a text file into a tab separated spreadsheet. My text file is something like this:



      Dog
      Cat
      Fish
      Lizard
      Wolf
      Lion
      Shark
      Gecko
      Coyote
      Puma
      Eel
      Iguana


      With standard search and replace functions in Gedit or LibreOffice, it's easyto replace the end of line with a tab. But if I just swap carriage returns for tabs, I'll get this:



      Dog Cat Fish Lizard Wolf Lion Shark Gecko Coyote Puma Eel Iguana


      But what I need to do is get it to look like this:



      Dog Cat Fish Lizard
      Wolf Lion Shark Gecko
      Coyote Puma Eel Iguana


      So, can I swap every end of line character for a tab except for every fourth line?



      I don't know if that kind of conditional iteration can be done with regular expressions inside a program like Gedit or LibreOffice, so maybe this needs to be some kind of command line function? I'm not even clear on what the best tool to start with is.




      Update:



      I tried the following commands:



      sed 'N;N;N;s/n/t/g' file > file.tsv

      paste - - - - < file > file.tsv

      pr -aT -s$'t' -4 file > file.tsv

      xargs -d 'n' -n4 < inputfile.txt


      But when I try to open the resulting tsv file in LibreOffice, the columns are not quite right. I'm not sure if this means I'm not executing the above commands correctly, or if I'm doing something wrong in the LibreOffice import function:



      TSV opening in Calc



      Just for reference, the desired result should look like this:



      Proper columns







      share|improve this question














      I am trying to convert a text file into a tab separated spreadsheet. My text file is something like this:



      Dog
      Cat
      Fish
      Lizard
      Wolf
      Lion
      Shark
      Gecko
      Coyote
      Puma
      Eel
      Iguana


      With standard search and replace functions in Gedit or LibreOffice, it's easyto replace the end of line with a tab. But if I just swap carriage returns for tabs, I'll get this:



      Dog Cat Fish Lizard Wolf Lion Shark Gecko Coyote Puma Eel Iguana


      But what I need to do is get it to look like this:



      Dog Cat Fish Lizard
      Wolf Lion Shark Gecko
      Coyote Puma Eel Iguana


      So, can I swap every end of line character for a tab except for every fourth line?



      I don't know if that kind of conditional iteration can be done with regular expressions inside a program like Gedit or LibreOffice, so maybe this needs to be some kind of command line function? I'm not even clear on what the best tool to start with is.




      Update:



      I tried the following commands:



      sed 'N;N;N;s/n/t/g' file > file.tsv

      paste - - - - < file > file.tsv

      pr -aT -s$'t' -4 file > file.tsv

      xargs -d 'n' -n4 < inputfile.txt


      But when I try to open the resulting tsv file in LibreOffice, the columns are not quite right. I'm not sure if this means I'm not executing the above commands correctly, or if I'm doing something wrong in the LibreOffice import function:



      TSV opening in Calc



      Just for reference, the desired result should look like this:



      Proper columns









      share|improve this question













      share|improve this question




      share|improve this question








      edited Apr 25 at 12:49

























      asked Apr 25 at 12:00









      Questioner

      1,4382480146




      1,4382480146




















          8 Answers
          8






          active

          oldest

          votes

















          up vote
          16
          down vote



          accepted










          You could use a command-line editor such as sed



          sed 'N;N;N;s/n/t/g' file > file.tsv


          or, more programatically, by adding backslash line continuation characters to each of the lines you want to join using GNU sed's n skip m address operator and following it with the classic one-liner for joining continued lines:



          sed '0~4! s/$/t\/' file | sed -e :a -e '/\$/N; s/\n//; ta'


          See for example Sed One-Liners Explained :





          1. Append a line to the next if it ends with a backslash "".



            sed -e :a -e '/\$/N; s/\n//; ta'




          However IMHO itwould be easier with one of the other standard text-processing utilities e.g.



          paste - - - - < file > file.tsv


          (the number of - will correspond to the number of columns) or



          pr -aT -s$'t' -4 file > file.tsv


          (you can omit the -s$'t if you don't mind the output to be separated by multiple tabs).




          The strange re-import behavior that you are observing is almost certainly because the original file has Windows-style CRLF line endings. If you need to work with files from Windows, then you can roll the conversion into the command in various ways e.g.



          tr -d 'r' < file.csv | paste - - - -


          or



          sed 'N;N;N;s/rn/t/g' file.csv


          The former will remove ALL carriage returns whereas the latter will preserve a CR at the end of each of the new lines (which may be what you want if the intended end user is on Windows).






          share|improve this answer


















          • 1




            A note about Windows-style line endings: the standard tools to convert between them and Unix-style are dos2unix and unix2dos.
            – David Foerster
            Apr 26 at 10:50

















          up vote
          13
          down vote













          You can use xargs to always group four lines into one, separated with a single space each:



          xargs -d 'n' -n4 < inputfile.txt


          -d 'n' sets the input delimiter to a newline character, otherwise it would also break on spaces. If you only have one word per input line anyway, you can even omit this.
          -n4 sets the argument number (the number of input items per output line) to 4.



          Output:



          Dog Cat Fish Lizard
          Wolf Lion Shark Gecko
          Coyote Puma Eel Iguana


          Or if you want tabs as separators instead of a space, you can replace them afterwards. However, if you had spaces in your input lines, those would get replaced too:



          xargs -d 'n' -n4 | tr ' ' 't'


          Output (look depending on browser/terminal's tab width):



          Dog Cat Fish Lizard
          Wolf Lion Shark Gecko
          Coyote Puma Eel Iguana





          share|improve this answer




















          • This method has the benefit that it behaves reasonably even when the total number of lines of input is not a multiple of four.
            – Eliah Kagan
            Apr 25 at 16:16

















          up vote
          3
          down vote













          You could also use:



          awk -v ORS="" 'print $1; print NR%4==0?"n":"t"' file > file.tsv 


          The two awk built-in variables are:




          • ORS: Output Record Separator(default=newline). It is added at the end of each print command.


          • NR: Number of the current Row awk is processing.

          This command will, for each line, display the content of the first (and here only) column. Then it choose to add a newline or a tab by testing the remainder of the division of NR by 4.






          share|improve this answer





























            up vote
            3
            down vote













            Another shortest awk approach:



            awk 'printf $0 (NR%4?"t":"n")' infile


            This printf the only one column followed by next and next and ... and a Tab t character after each but will printf a newline character when Number of Record was factor of 4 (where NR%4 will return 0 (false) which is what Ternary Operator condition(s)?when-true:when-false is doing.)






            share|improve this answer





























              up vote
              3
              down vote













              My solution to this would be to use combination of sed and sed. First, you could mark every fourth line with some special character, for example >, using this solution:



              • Adding a character to every other text line

              In this case you want to start from line 5 and mark every 4th line after it. In GNU sed that can be given as an address 5~4. You can use this command:



              sed '5~4s/^/>/' file1 > file2


              Then you need to remove the newlines, which can be done with a sed loop:



              sed ':a;N;s/n/ /;ba' file2 > file3


              There are easier ways to convert newlines to some other character, for example with tr:



              tr 'n' ' ' < file2 > file3


              Either way, combining the two gives



              Dog Cat Fish Lizard >Wolf Lion Shark Gecko >Coyote Puma Eel Iguana


              (the sed version leaves a trailing newline, while the tr version does not)



              After that, you need only convert the special characters you inserted to newlines; see for example Convert a tab-delimited file to use newlines. In this case, change > to newlines:



              sed 'y/>/n/' file3 > outfile


              The y command performs the same function as tr, transforming one character into another, but you can use the s command here equally well. With s, you need g to operate on each match in the line (sed 's/>/n/g').



              Rather than making two intermediate files, you can use pipes:



              $ sed '5~4s/^/>/' file | sed ':a;N;s/n/ /;ba' | sed 'y/>/n/'
              Dog Cat Fish Lizard
              Wolf Lion Shark Gecko
              Coyote Puma Eel Iguana


              If trailing spaces are a problem, you can add another command to remove them:



              | sed 's/ $//'





              share|improve this answer





























                up vote
                2
                down vote













                For the sake of "completeness" here's a pure bash solution:



                #!/usr/bin/env bash

                sep=$'t'

                while read one
                && read two
                && read three
                && read four
                do
                printf "%sn" "$one$sep$two$sep$three$sep$four"
                done


                Works also with spaces, assuming IFS is properly set (which it should by default, AFAIK). Moreover, I think this could even be a portable shell script and work with any POSIX compatible shell.






                share|improve this answer


















                • 1




                  This isn't portable to POSIX compatible shells in general, because the $' ' form of quoting is not required by POSIX. For example, in dash (which provides sh by default on Ubuntu), running printf '%sn' $'atb' just outputs $atb. That doesn't mean this isn't useful though; it does work in bash. However, as with some of the other solutions people have posted, it produces incomplete output if the number of lines of input is not a multiple of four. Also, I recommend using read -r, since there's no reason to think the expansion of backslash escapes in the input file is desired here.
                  – Eliah Kagan
                  Apr 25 at 18:14











                • You could simply do printf '%st%st%st%sn' "$one" "$two" "$three" "$four"
                  – terdon♦
                  Apr 26 at 8:59

















                up vote
                2
                down vote













                A vim macro (recorded with q) could apply your operation, then skip three lines. Then, you just run that macro n times.



                eg:



                qq $ J i <TAB> <ESC> $ J i <TAB> <ESC> $ J i <TAB> <ESC> ^^ j qq 100 @q





                share|improve this answer



























                  up vote
                  2
                  down vote













                  Since you asked for a Gedit solution, something like this should work:



                  Find:



                  (w+)[rn]+(w+)[rn]+(w+)[rn]+(w+)[rn]+


                  Replace with:



                  1t2t3t4n


                  Make sure that the checkbox for regular expressions is marked.



                  How it works:



                  The first step is to find a series of word characters, with w+, and capture the results in the variable 1 by wrapping parentheses around the expression:



                  (w+)


                  Next we search for a series of line ending characters, r and n, or CR and LF. Since Windows formatted files use both, we create a character class by wrapping these two characters in square brackets. The plus makes it search for one or more characters:



                  [rn]+


                  Finally, we repeat this 3 more times, storing each subsequent word in variables 2, 3, and 4. This makes our replace with expression simple. We just need to place tab characters, t, and a new line character, n, in the appropriate places for the formatting you need.






                  share|improve this answer






















                    Your Answer







                    StackExchange.ready(function()
                    var channelOptions =
                    tags: "".split(" "),
                    id: "89"
                    ;
                    initTagRenderer("".split(" "), "".split(" "), channelOptions);

                    StackExchange.using("externalEditor", function()
                    // Have to fire editor after snippets, if snippets enabled
                    if (StackExchange.settings.snippets.snippetsEnabled)
                    StackExchange.using("snippets", function()
                    createEditor();
                    );

                    else
                    createEditor();

                    );

                    function createEditor()
                    StackExchange.prepareEditor(
                    heartbeatType: 'answer',
                    convertImagesToLinks: true,
                    noModals: false,
                    showLowRepImageUploadWarning: true,
                    reputationToPostImages: 10,
                    bindNavPrevention: true,
                    postfix: "",
                    onDemand: true,
                    discardSelector: ".discard-answer"
                    ,immediatelyShowMarkdownHelp:true
                    );



                    );













                     

                    draft saved


                    draft discarded


















                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f1028074%2fis-it-possible-with-gedit-or-the-command-line-to-modify-every-fourth-line-of-a-t%23new-answer', 'question_page');

                    );

                    Post as a guest






























                    8 Answers
                    8






                    active

                    oldest

                    votes








                    8 Answers
                    8






                    active

                    oldest

                    votes









                    active

                    oldest

                    votes






                    active

                    oldest

                    votes








                    up vote
                    16
                    down vote



                    accepted










                    You could use a command-line editor such as sed



                    sed 'N;N;N;s/n/t/g' file > file.tsv


                    or, more programatically, by adding backslash line continuation characters to each of the lines you want to join using GNU sed's n skip m address operator and following it with the classic one-liner for joining continued lines:



                    sed '0~4! s/$/t\/' file | sed -e :a -e '/\$/N; s/\n//; ta'


                    See for example Sed One-Liners Explained :





                    1. Append a line to the next if it ends with a backslash "".



                      sed -e :a -e '/\$/N; s/\n//; ta'




                    However IMHO itwould be easier with one of the other standard text-processing utilities e.g.



                    paste - - - - < file > file.tsv


                    (the number of - will correspond to the number of columns) or



                    pr -aT -s$'t' -4 file > file.tsv


                    (you can omit the -s$'t if you don't mind the output to be separated by multiple tabs).




                    The strange re-import behavior that you are observing is almost certainly because the original file has Windows-style CRLF line endings. If you need to work with files from Windows, then you can roll the conversion into the command in various ways e.g.



                    tr -d 'r' < file.csv | paste - - - -


                    or



                    sed 'N;N;N;s/rn/t/g' file.csv


                    The former will remove ALL carriage returns whereas the latter will preserve a CR at the end of each of the new lines (which may be what you want if the intended end user is on Windows).






                    share|improve this answer


















                    • 1




                      A note about Windows-style line endings: the standard tools to convert between them and Unix-style are dos2unix and unix2dos.
                      – David Foerster
                      Apr 26 at 10:50














                    up vote
                    16
                    down vote



                    accepted










                    You could use a command-line editor such as sed



                    sed 'N;N;N;s/n/t/g' file > file.tsv


                    or, more programatically, by adding backslash line continuation characters to each of the lines you want to join using GNU sed's n skip m address operator and following it with the classic one-liner for joining continued lines:



                    sed '0~4! s/$/t\/' file | sed -e :a -e '/\$/N; s/\n//; ta'


                    See for example Sed One-Liners Explained :





                    1. Append a line to the next if it ends with a backslash "".



                      sed -e :a -e '/\$/N; s/\n//; ta'




                    However IMHO itwould be easier with one of the other standard text-processing utilities e.g.



                    paste - - - - < file > file.tsv


                    (the number of - will correspond to the number of columns) or



                    pr -aT -s$'t' -4 file > file.tsv


                    (you can omit the -s$'t if you don't mind the output to be separated by multiple tabs).




                    The strange re-import behavior that you are observing is almost certainly because the original file has Windows-style CRLF line endings. If you need to work with files from Windows, then you can roll the conversion into the command in various ways e.g.



                    tr -d 'r' < file.csv | paste - - - -


                    or



                    sed 'N;N;N;s/rn/t/g' file.csv


                    The former will remove ALL carriage returns whereas the latter will preserve a CR at the end of each of the new lines (which may be what you want if the intended end user is on Windows).






                    share|improve this answer


















                    • 1




                      A note about Windows-style line endings: the standard tools to convert between them and Unix-style are dos2unix and unix2dos.
                      – David Foerster
                      Apr 26 at 10:50












                    up vote
                    16
                    down vote



                    accepted







                    up vote
                    16
                    down vote



                    accepted






                    You could use a command-line editor such as sed



                    sed 'N;N;N;s/n/t/g' file > file.tsv


                    or, more programatically, by adding backslash line continuation characters to each of the lines you want to join using GNU sed's n skip m address operator and following it with the classic one-liner for joining continued lines:



                    sed '0~4! s/$/t\/' file | sed -e :a -e '/\$/N; s/\n//; ta'


                    See for example Sed One-Liners Explained :





                    1. Append a line to the next if it ends with a backslash "".



                      sed -e :a -e '/\$/N; s/\n//; ta'




                    However IMHO itwould be easier with one of the other standard text-processing utilities e.g.



                    paste - - - - < file > file.tsv


                    (the number of - will correspond to the number of columns) or



                    pr -aT -s$'t' -4 file > file.tsv


                    (you can omit the -s$'t if you don't mind the output to be separated by multiple tabs).




                    The strange re-import behavior that you are observing is almost certainly because the original file has Windows-style CRLF line endings. If you need to work with files from Windows, then you can roll the conversion into the command in various ways e.g.



                    tr -d 'r' < file.csv | paste - - - -


                    or



                    sed 'N;N;N;s/rn/t/g' file.csv


                    The former will remove ALL carriage returns whereas the latter will preserve a CR at the end of each of the new lines (which may be what you want if the intended end user is on Windows).






                    share|improve this answer














                    You could use a command-line editor such as sed



                    sed 'N;N;N;s/n/t/g' file > file.tsv


                    or, more programatically, by adding backslash line continuation characters to each of the lines you want to join using GNU sed's n skip m address operator and following it with the classic one-liner for joining continued lines:



                    sed '0~4! s/$/t\/' file | sed -e :a -e '/\$/N; s/\n//; ta'


                    See for example Sed One-Liners Explained :





                    1. Append a line to the next if it ends with a backslash "".



                      sed -e :a -e '/\$/N; s/\n//; ta'




                    However IMHO itwould be easier with one of the other standard text-processing utilities e.g.



                    paste - - - - < file > file.tsv


                    (the number of - will correspond to the number of columns) or



                    pr -aT -s$'t' -4 file > file.tsv


                    (you can omit the -s$'t if you don't mind the output to be separated by multiple tabs).




                    The strange re-import behavior that you are observing is almost certainly because the original file has Windows-style CRLF line endings. If you need to work with files from Windows, then you can roll the conversion into the command in various ways e.g.



                    tr -d 'r' < file.csv | paste - - - -


                    or



                    sed 'N;N;N;s/rn/t/g' file.csv


                    The former will remove ALL carriage returns whereas the latter will preserve a CR at the end of each of the new lines (which may be what you want if the intended end user is on Windows).







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Apr 25 at 14:32

























                    answered Apr 25 at 12:07









                    steeldriver

                    62.7k1196165




                    62.7k1196165







                    • 1




                      A note about Windows-style line endings: the standard tools to convert between them and Unix-style are dos2unix and unix2dos.
                      – David Foerster
                      Apr 26 at 10:50












                    • 1




                      A note about Windows-style line endings: the standard tools to convert between them and Unix-style are dos2unix and unix2dos.
                      – David Foerster
                      Apr 26 at 10:50







                    1




                    1




                    A note about Windows-style line endings: the standard tools to convert between them and Unix-style are dos2unix and unix2dos.
                    – David Foerster
                    Apr 26 at 10:50




                    A note about Windows-style line endings: the standard tools to convert between them and Unix-style are dos2unix and unix2dos.
                    – David Foerster
                    Apr 26 at 10:50












                    up vote
                    13
                    down vote













                    You can use xargs to always group four lines into one, separated with a single space each:



                    xargs -d 'n' -n4 < inputfile.txt


                    -d 'n' sets the input delimiter to a newline character, otherwise it would also break on spaces. If you only have one word per input line anyway, you can even omit this.
                    -n4 sets the argument number (the number of input items per output line) to 4.



                    Output:



                    Dog Cat Fish Lizard
                    Wolf Lion Shark Gecko
                    Coyote Puma Eel Iguana


                    Or if you want tabs as separators instead of a space, you can replace them afterwards. However, if you had spaces in your input lines, those would get replaced too:



                    xargs -d 'n' -n4 | tr ' ' 't'


                    Output (look depending on browser/terminal's tab width):



                    Dog Cat Fish Lizard
                    Wolf Lion Shark Gecko
                    Coyote Puma Eel Iguana





                    share|improve this answer




















                    • This method has the benefit that it behaves reasonably even when the total number of lines of input is not a multiple of four.
                      – Eliah Kagan
                      Apr 25 at 16:16














                    up vote
                    13
                    down vote













                    You can use xargs to always group four lines into one, separated with a single space each:



                    xargs -d 'n' -n4 < inputfile.txt


                    -d 'n' sets the input delimiter to a newline character, otherwise it would also break on spaces. If you only have one word per input line anyway, you can even omit this.
                    -n4 sets the argument number (the number of input items per output line) to 4.



                    Output:



                    Dog Cat Fish Lizard
                    Wolf Lion Shark Gecko
                    Coyote Puma Eel Iguana


                    Or if you want tabs as separators instead of a space, you can replace them afterwards. However, if you had spaces in your input lines, those would get replaced too:



                    xargs -d 'n' -n4 | tr ' ' 't'


                    Output (look depending on browser/terminal's tab width):



                    Dog Cat Fish Lizard
                    Wolf Lion Shark Gecko
                    Coyote Puma Eel Iguana





                    share|improve this answer




















                    • This method has the benefit that it behaves reasonably even when the total number of lines of input is not a multiple of four.
                      – Eliah Kagan
                      Apr 25 at 16:16












                    up vote
                    13
                    down vote










                    up vote
                    13
                    down vote









                    You can use xargs to always group four lines into one, separated with a single space each:



                    xargs -d 'n' -n4 < inputfile.txt


                    -d 'n' sets the input delimiter to a newline character, otherwise it would also break on spaces. If you only have one word per input line anyway, you can even omit this.
                    -n4 sets the argument number (the number of input items per output line) to 4.



                    Output:



                    Dog Cat Fish Lizard
                    Wolf Lion Shark Gecko
                    Coyote Puma Eel Iguana


                    Or if you want tabs as separators instead of a space, you can replace them afterwards. However, if you had spaces in your input lines, those would get replaced too:



                    xargs -d 'n' -n4 | tr ' ' 't'


                    Output (look depending on browser/terminal's tab width):



                    Dog Cat Fish Lizard
                    Wolf Lion Shark Gecko
                    Coyote Puma Eel Iguana





                    share|improve this answer












                    You can use xargs to always group four lines into one, separated with a single space each:



                    xargs -d 'n' -n4 < inputfile.txt


                    -d 'n' sets the input delimiter to a newline character, otherwise it would also break on spaces. If you only have one word per input line anyway, you can even omit this.
                    -n4 sets the argument number (the number of input items per output line) to 4.



                    Output:



                    Dog Cat Fish Lizard
                    Wolf Lion Shark Gecko
                    Coyote Puma Eel Iguana


                    Or if you want tabs as separators instead of a space, you can replace them afterwards. However, if you had spaces in your input lines, those would get replaced too:



                    xargs -d 'n' -n4 | tr ' ' 't'


                    Output (look depending on browser/terminal's tab width):



                    Dog Cat Fish Lizard
                    Wolf Lion Shark Gecko
                    Coyote Puma Eel Iguana






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Apr 25 at 12:19









                    Byte Commander

                    59.2k26158267




                    59.2k26158267











                    • This method has the benefit that it behaves reasonably even when the total number of lines of input is not a multiple of four.
                      – Eliah Kagan
                      Apr 25 at 16:16
















                    • This method has the benefit that it behaves reasonably even when the total number of lines of input is not a multiple of four.
                      – Eliah Kagan
                      Apr 25 at 16:16















                    This method has the benefit that it behaves reasonably even when the total number of lines of input is not a multiple of four.
                    – Eliah Kagan
                    Apr 25 at 16:16




                    This method has the benefit that it behaves reasonably even when the total number of lines of input is not a multiple of four.
                    – Eliah Kagan
                    Apr 25 at 16:16










                    up vote
                    3
                    down vote













                    You could also use:



                    awk -v ORS="" 'print $1; print NR%4==0?"n":"t"' file > file.tsv 


                    The two awk built-in variables are:




                    • ORS: Output Record Separator(default=newline). It is added at the end of each print command.


                    • NR: Number of the current Row awk is processing.

                    This command will, for each line, display the content of the first (and here only) column. Then it choose to add a newline or a tab by testing the remainder of the division of NR by 4.






                    share|improve this answer


























                      up vote
                      3
                      down vote













                      You could also use:



                      awk -v ORS="" 'print $1; print NR%4==0?"n":"t"' file > file.tsv 


                      The two awk built-in variables are:




                      • ORS: Output Record Separator(default=newline). It is added at the end of each print command.


                      • NR: Number of the current Row awk is processing.

                      This command will, for each line, display the content of the first (and here only) column. Then it choose to add a newline or a tab by testing the remainder of the division of NR by 4.






                      share|improve this answer
























                        up vote
                        3
                        down vote










                        up vote
                        3
                        down vote









                        You could also use:



                        awk -v ORS="" 'print $1; print NR%4==0?"n":"t"' file > file.tsv 


                        The two awk built-in variables are:




                        • ORS: Output Record Separator(default=newline). It is added at the end of each print command.


                        • NR: Number of the current Row awk is processing.

                        This command will, for each line, display the content of the first (and here only) column. Then it choose to add a newline or a tab by testing the remainder of the division of NR by 4.






                        share|improve this answer














                        You could also use:



                        awk -v ORS="" 'print $1; print NR%4==0?"n":"t"' file > file.tsv 


                        The two awk built-in variables are:




                        • ORS: Output Record Separator(default=newline). It is added at the end of each print command.


                        • NR: Number of the current Row awk is processing.

                        This command will, for each line, display the content of the first (and here only) column. Then it choose to add a newline or a tab by testing the remainder of the division of NR by 4.







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Apr 25 at 18:10









                        Eliah Kagan

                        79.4k20221359




                        79.4k20221359










                        answered Apr 25 at 18:07









                        arauk

                        311




                        311




















                            up vote
                            3
                            down vote













                            Another shortest awk approach:



                            awk 'printf $0 (NR%4?"t":"n")' infile


                            This printf the only one column followed by next and next and ... and a Tab t character after each but will printf a newline character when Number of Record was factor of 4 (where NR%4 will return 0 (false) which is what Ternary Operator condition(s)?when-true:when-false is doing.)






                            share|improve this answer


























                              up vote
                              3
                              down vote













                              Another shortest awk approach:



                              awk 'printf $0 (NR%4?"t":"n")' infile


                              This printf the only one column followed by next and next and ... and a Tab t character after each but will printf a newline character when Number of Record was factor of 4 (where NR%4 will return 0 (false) which is what Ternary Operator condition(s)?when-true:when-false is doing.)






                              share|improve this answer
























                                up vote
                                3
                                down vote










                                up vote
                                3
                                down vote









                                Another shortest awk approach:



                                awk 'printf $0 (NR%4?"t":"n")' infile


                                This printf the only one column followed by next and next and ... and a Tab t character after each but will printf a newline character when Number of Record was factor of 4 (where NR%4 will return 0 (false) which is what Ternary Operator condition(s)?when-true:when-false is doing.)






                                share|improve this answer














                                Another shortest awk approach:



                                awk 'printf $0 (NR%4?"t":"n")' infile


                                This printf the only one column followed by next and next and ... and a Tab t character after each but will printf a newline character when Number of Record was factor of 4 (where NR%4 will return 0 (false) which is what Ternary Operator condition(s)?when-true:when-false is doing.)







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited Apr 26 at 8:05

























                                answered Apr 26 at 4:59









                                αғsнιη

                                23.2k2191152




                                23.2k2191152




















                                    up vote
                                    3
                                    down vote













                                    My solution to this would be to use combination of sed and sed. First, you could mark every fourth line with some special character, for example >, using this solution:



                                    • Adding a character to every other text line

                                    In this case you want to start from line 5 and mark every 4th line after it. In GNU sed that can be given as an address 5~4. You can use this command:



                                    sed '5~4s/^/>/' file1 > file2


                                    Then you need to remove the newlines, which can be done with a sed loop:



                                    sed ':a;N;s/n/ /;ba' file2 > file3


                                    There are easier ways to convert newlines to some other character, for example with tr:



                                    tr 'n' ' ' < file2 > file3


                                    Either way, combining the two gives



                                    Dog Cat Fish Lizard >Wolf Lion Shark Gecko >Coyote Puma Eel Iguana


                                    (the sed version leaves a trailing newline, while the tr version does not)



                                    After that, you need only convert the special characters you inserted to newlines; see for example Convert a tab-delimited file to use newlines. In this case, change > to newlines:



                                    sed 'y/>/n/' file3 > outfile


                                    The y command performs the same function as tr, transforming one character into another, but you can use the s command here equally well. With s, you need g to operate on each match in the line (sed 's/>/n/g').



                                    Rather than making two intermediate files, you can use pipes:



                                    $ sed '5~4s/^/>/' file | sed ':a;N;s/n/ /;ba' | sed 'y/>/n/'
                                    Dog Cat Fish Lizard
                                    Wolf Lion Shark Gecko
                                    Coyote Puma Eel Iguana


                                    If trailing spaces are a problem, you can add another command to remove them:



                                    | sed 's/ $//'





                                    share|improve this answer


























                                      up vote
                                      3
                                      down vote













                                      My solution to this would be to use combination of sed and sed. First, you could mark every fourth line with some special character, for example >, using this solution:



                                      • Adding a character to every other text line

                                      In this case you want to start from line 5 and mark every 4th line after it. In GNU sed that can be given as an address 5~4. You can use this command:



                                      sed '5~4s/^/>/' file1 > file2


                                      Then you need to remove the newlines, which can be done with a sed loop:



                                      sed ':a;N;s/n/ /;ba' file2 > file3


                                      There are easier ways to convert newlines to some other character, for example with tr:



                                      tr 'n' ' ' < file2 > file3


                                      Either way, combining the two gives



                                      Dog Cat Fish Lizard >Wolf Lion Shark Gecko >Coyote Puma Eel Iguana


                                      (the sed version leaves a trailing newline, while the tr version does not)



                                      After that, you need only convert the special characters you inserted to newlines; see for example Convert a tab-delimited file to use newlines. In this case, change > to newlines:



                                      sed 'y/>/n/' file3 > outfile


                                      The y command performs the same function as tr, transforming one character into another, but you can use the s command here equally well. With s, you need g to operate on each match in the line (sed 's/>/n/g').



                                      Rather than making two intermediate files, you can use pipes:



                                      $ sed '5~4s/^/>/' file | sed ':a;N;s/n/ /;ba' | sed 'y/>/n/'
                                      Dog Cat Fish Lizard
                                      Wolf Lion Shark Gecko
                                      Coyote Puma Eel Iguana


                                      If trailing spaces are a problem, you can add another command to remove them:



                                      | sed 's/ $//'





                                      share|improve this answer
























                                        up vote
                                        3
                                        down vote










                                        up vote
                                        3
                                        down vote









                                        My solution to this would be to use combination of sed and sed. First, you could mark every fourth line with some special character, for example >, using this solution:



                                        • Adding a character to every other text line

                                        In this case you want to start from line 5 and mark every 4th line after it. In GNU sed that can be given as an address 5~4. You can use this command:



                                        sed '5~4s/^/>/' file1 > file2


                                        Then you need to remove the newlines, which can be done with a sed loop:



                                        sed ':a;N;s/n/ /;ba' file2 > file3


                                        There are easier ways to convert newlines to some other character, for example with tr:



                                        tr 'n' ' ' < file2 > file3


                                        Either way, combining the two gives



                                        Dog Cat Fish Lizard >Wolf Lion Shark Gecko >Coyote Puma Eel Iguana


                                        (the sed version leaves a trailing newline, while the tr version does not)



                                        After that, you need only convert the special characters you inserted to newlines; see for example Convert a tab-delimited file to use newlines. In this case, change > to newlines:



                                        sed 'y/>/n/' file3 > outfile


                                        The y command performs the same function as tr, transforming one character into another, but you can use the s command here equally well. With s, you need g to operate on each match in the line (sed 's/>/n/g').



                                        Rather than making two intermediate files, you can use pipes:



                                        $ sed '5~4s/^/>/' file | sed ':a;N;s/n/ /;ba' | sed 'y/>/n/'
                                        Dog Cat Fish Lizard
                                        Wolf Lion Shark Gecko
                                        Coyote Puma Eel Iguana


                                        If trailing spaces are a problem, you can add another command to remove them:



                                        | sed 's/ $//'





                                        share|improve this answer














                                        My solution to this would be to use combination of sed and sed. First, you could mark every fourth line with some special character, for example >, using this solution:



                                        • Adding a character to every other text line

                                        In this case you want to start from line 5 and mark every 4th line after it. In GNU sed that can be given as an address 5~4. You can use this command:



                                        sed '5~4s/^/>/' file1 > file2


                                        Then you need to remove the newlines, which can be done with a sed loop:



                                        sed ':a;N;s/n/ /;ba' file2 > file3


                                        There are easier ways to convert newlines to some other character, for example with tr:



                                        tr 'n' ' ' < file2 > file3


                                        Either way, combining the two gives



                                        Dog Cat Fish Lizard >Wolf Lion Shark Gecko >Coyote Puma Eel Iguana


                                        (the sed version leaves a trailing newline, while the tr version does not)



                                        After that, you need only convert the special characters you inserted to newlines; see for example Convert a tab-delimited file to use newlines. In this case, change > to newlines:



                                        sed 'y/>/n/' file3 > outfile


                                        The y command performs the same function as tr, transforming one character into another, but you can use the s command here equally well. With s, you need g to operate on each match in the line (sed 's/>/n/g').



                                        Rather than making two intermediate files, you can use pipes:



                                        $ sed '5~4s/^/>/' file | sed ':a;N;s/n/ /;ba' | sed 'y/>/n/'
                                        Dog Cat Fish Lizard
                                        Wolf Lion Shark Gecko
                                        Coyote Puma Eel Iguana


                                        If trailing spaces are a problem, you can add another command to remove them:



                                        | sed 's/ $//'






                                        share|improve this answer














                                        share|improve this answer



                                        share|improve this answer








                                        edited Apr 26 at 8:39









                                        Zanna

                                        48k13119227




                                        48k13119227










                                        answered Apr 25 at 12:26









                                        spaceman117X

                                        1647




                                        1647




















                                            up vote
                                            2
                                            down vote













                                            For the sake of "completeness" here's a pure bash solution:



                                            #!/usr/bin/env bash

                                            sep=$'t'

                                            while read one
                                            && read two
                                            && read three
                                            && read four
                                            do
                                            printf "%sn" "$one$sep$two$sep$three$sep$four"
                                            done


                                            Works also with spaces, assuming IFS is properly set (which it should by default, AFAIK). Moreover, I think this could even be a portable shell script and work with any POSIX compatible shell.






                                            share|improve this answer


















                                            • 1




                                              This isn't portable to POSIX compatible shells in general, because the $' ' form of quoting is not required by POSIX. For example, in dash (which provides sh by default on Ubuntu), running printf '%sn' $'atb' just outputs $atb. That doesn't mean this isn't useful though; it does work in bash. However, as with some of the other solutions people have posted, it produces incomplete output if the number of lines of input is not a multiple of four. Also, I recommend using read -r, since there's no reason to think the expansion of backslash escapes in the input file is desired here.
                                              – Eliah Kagan
                                              Apr 25 at 18:14











                                            • You could simply do printf '%st%st%st%sn' "$one" "$two" "$three" "$four"
                                              – terdon♦
                                              Apr 26 at 8:59














                                            up vote
                                            2
                                            down vote













                                            For the sake of "completeness" here's a pure bash solution:



                                            #!/usr/bin/env bash

                                            sep=$'t'

                                            while read one
                                            && read two
                                            && read three
                                            && read four
                                            do
                                            printf "%sn" "$one$sep$two$sep$three$sep$four"
                                            done


                                            Works also with spaces, assuming IFS is properly set (which it should by default, AFAIK). Moreover, I think this could even be a portable shell script and work with any POSIX compatible shell.






                                            share|improve this answer


















                                            • 1




                                              This isn't portable to POSIX compatible shells in general, because the $' ' form of quoting is not required by POSIX. For example, in dash (which provides sh by default on Ubuntu), running printf '%sn' $'atb' just outputs $atb. That doesn't mean this isn't useful though; it does work in bash. However, as with some of the other solutions people have posted, it produces incomplete output if the number of lines of input is not a multiple of four. Also, I recommend using read -r, since there's no reason to think the expansion of backslash escapes in the input file is desired here.
                                              – Eliah Kagan
                                              Apr 25 at 18:14











                                            • You could simply do printf '%st%st%st%sn' "$one" "$two" "$three" "$four"
                                              – terdon♦
                                              Apr 26 at 8:59












                                            up vote
                                            2
                                            down vote










                                            up vote
                                            2
                                            down vote









                                            For the sake of "completeness" here's a pure bash solution:



                                            #!/usr/bin/env bash

                                            sep=$'t'

                                            while read one
                                            && read two
                                            && read three
                                            && read four
                                            do
                                            printf "%sn" "$one$sep$two$sep$three$sep$four"
                                            done


                                            Works also with spaces, assuming IFS is properly set (which it should by default, AFAIK). Moreover, I think this could even be a portable shell script and work with any POSIX compatible shell.






                                            share|improve this answer














                                            For the sake of "completeness" here's a pure bash solution:



                                            #!/usr/bin/env bash

                                            sep=$'t'

                                            while read one
                                            && read two
                                            && read three
                                            && read four
                                            do
                                            printf "%sn" "$one$sep$two$sep$three$sep$four"
                                            done


                                            Works also with spaces, assuming IFS is properly set (which it should by default, AFAIK). Moreover, I think this could even be a portable shell script and work with any POSIX compatible shell.







                                            share|improve this answer














                                            share|improve this answer



                                            share|improve this answer








                                            edited Apr 25 at 17:48









                                            dessert

                                            19.8k55594




                                            19.8k55594










                                            answered Apr 25 at 17:31









                                            Daniel Jour

                                            1214




                                            1214







                                            • 1




                                              This isn't portable to POSIX compatible shells in general, because the $' ' form of quoting is not required by POSIX. For example, in dash (which provides sh by default on Ubuntu), running printf '%sn' $'atb' just outputs $atb. That doesn't mean this isn't useful though; it does work in bash. However, as with some of the other solutions people have posted, it produces incomplete output if the number of lines of input is not a multiple of four. Also, I recommend using read -r, since there's no reason to think the expansion of backslash escapes in the input file is desired here.
                                              – Eliah Kagan
                                              Apr 25 at 18:14











                                            • You could simply do printf '%st%st%st%sn' "$one" "$two" "$three" "$four"
                                              – terdon♦
                                              Apr 26 at 8:59












                                            • 1




                                              This isn't portable to POSIX compatible shells in general, because the $' ' form of quoting is not required by POSIX. For example, in dash (which provides sh by default on Ubuntu), running printf '%sn' $'atb' just outputs $atb. That doesn't mean this isn't useful though; it does work in bash. However, as with some of the other solutions people have posted, it produces incomplete output if the number of lines of input is not a multiple of four. Also, I recommend using read -r, since there's no reason to think the expansion of backslash escapes in the input file is desired here.
                                              – Eliah Kagan
                                              Apr 25 at 18:14











                                            • You could simply do printf '%st%st%st%sn' "$one" "$two" "$three" "$four"
                                              – terdon♦
                                              Apr 26 at 8:59







                                            1




                                            1




                                            This isn't portable to POSIX compatible shells in general, because the $' ' form of quoting is not required by POSIX. For example, in dash (which provides sh by default on Ubuntu), running printf '%sn' $'atb' just outputs $atb. That doesn't mean this isn't useful though; it does work in bash. However, as with some of the other solutions people have posted, it produces incomplete output if the number of lines of input is not a multiple of four. Also, I recommend using read -r, since there's no reason to think the expansion of backslash escapes in the input file is desired here.
                                            – Eliah Kagan
                                            Apr 25 at 18:14





                                            This isn't portable to POSIX compatible shells in general, because the $' ' form of quoting is not required by POSIX. For example, in dash (which provides sh by default on Ubuntu), running printf '%sn' $'atb' just outputs $atb. That doesn't mean this isn't useful though; it does work in bash. However, as with some of the other solutions people have posted, it produces incomplete output if the number of lines of input is not a multiple of four. Also, I recommend using read -r, since there's no reason to think the expansion of backslash escapes in the input file is desired here.
                                            – Eliah Kagan
                                            Apr 25 at 18:14













                                            You could simply do printf '%st%st%st%sn' "$one" "$two" "$three" "$four"
                                            – terdon♦
                                            Apr 26 at 8:59




                                            You could simply do printf '%st%st%st%sn' "$one" "$two" "$three" "$four"
                                            – terdon♦
                                            Apr 26 at 8:59










                                            up vote
                                            2
                                            down vote













                                            A vim macro (recorded with q) could apply your operation, then skip three lines. Then, you just run that macro n times.



                                            eg:



                                            qq $ J i <TAB> <ESC> $ J i <TAB> <ESC> $ J i <TAB> <ESC> ^^ j qq 100 @q





                                            share|improve this answer
























                                              up vote
                                              2
                                              down vote













                                              A vim macro (recorded with q) could apply your operation, then skip three lines. Then, you just run that macro n times.



                                              eg:



                                              qq $ J i <TAB> <ESC> $ J i <TAB> <ESC> $ J i <TAB> <ESC> ^^ j qq 100 @q





                                              share|improve this answer






















                                                up vote
                                                2
                                                down vote










                                                up vote
                                                2
                                                down vote









                                                A vim macro (recorded with q) could apply your operation, then skip three lines. Then, you just run that macro n times.



                                                eg:



                                                qq $ J i <TAB> <ESC> $ J i <TAB> <ESC> $ J i <TAB> <ESC> ^^ j qq 100 @q





                                                share|improve this answer












                                                A vim macro (recorded with q) could apply your operation, then skip three lines. Then, you just run that macro n times.



                                                eg:



                                                qq $ J i <TAB> <ESC> $ J i <TAB> <ESC> $ J i <TAB> <ESC> ^^ j qq 100 @q






                                                share|improve this answer












                                                share|improve this answer



                                                share|improve this answer










                                                answered Apr 25 at 22:10









                                                rackandboneman

                                                24316




                                                24316




















                                                    up vote
                                                    2
                                                    down vote













                                                    Since you asked for a Gedit solution, something like this should work:



                                                    Find:



                                                    (w+)[rn]+(w+)[rn]+(w+)[rn]+(w+)[rn]+


                                                    Replace with:



                                                    1t2t3t4n


                                                    Make sure that the checkbox for regular expressions is marked.



                                                    How it works:



                                                    The first step is to find a series of word characters, with w+, and capture the results in the variable 1 by wrapping parentheses around the expression:



                                                    (w+)


                                                    Next we search for a series of line ending characters, r and n, or CR and LF. Since Windows formatted files use both, we create a character class by wrapping these two characters in square brackets. The plus makes it search for one or more characters:



                                                    [rn]+


                                                    Finally, we repeat this 3 more times, storing each subsequent word in variables 2, 3, and 4. This makes our replace with expression simple. We just need to place tab characters, t, and a new line character, n, in the appropriate places for the formatting you need.






                                                    share|improve this answer


























                                                      up vote
                                                      2
                                                      down vote













                                                      Since you asked for a Gedit solution, something like this should work:



                                                      Find:



                                                      (w+)[rn]+(w+)[rn]+(w+)[rn]+(w+)[rn]+


                                                      Replace with:



                                                      1t2t3t4n


                                                      Make sure that the checkbox for regular expressions is marked.



                                                      How it works:



                                                      The first step is to find a series of word characters, with w+, and capture the results in the variable 1 by wrapping parentheses around the expression:



                                                      (w+)


                                                      Next we search for a series of line ending characters, r and n, or CR and LF. Since Windows formatted files use both, we create a character class by wrapping these two characters in square brackets. The plus makes it search for one or more characters:



                                                      [rn]+


                                                      Finally, we repeat this 3 more times, storing each subsequent word in variables 2, 3, and 4. This makes our replace with expression simple. We just need to place tab characters, t, and a new line character, n, in the appropriate places for the formatting you need.






                                                      share|improve this answer
























                                                        up vote
                                                        2
                                                        down vote










                                                        up vote
                                                        2
                                                        down vote









                                                        Since you asked for a Gedit solution, something like this should work:



                                                        Find:



                                                        (w+)[rn]+(w+)[rn]+(w+)[rn]+(w+)[rn]+


                                                        Replace with:



                                                        1t2t3t4n


                                                        Make sure that the checkbox for regular expressions is marked.



                                                        How it works:



                                                        The first step is to find a series of word characters, with w+, and capture the results in the variable 1 by wrapping parentheses around the expression:



                                                        (w+)


                                                        Next we search for a series of line ending characters, r and n, or CR and LF. Since Windows formatted files use both, we create a character class by wrapping these two characters in square brackets. The plus makes it search for one or more characters:



                                                        [rn]+


                                                        Finally, we repeat this 3 more times, storing each subsequent word in variables 2, 3, and 4. This makes our replace with expression simple. We just need to place tab characters, t, and a new line character, n, in the appropriate places for the formatting you need.






                                                        share|improve this answer














                                                        Since you asked for a Gedit solution, something like this should work:



                                                        Find:



                                                        (w+)[rn]+(w+)[rn]+(w+)[rn]+(w+)[rn]+


                                                        Replace with:



                                                        1t2t3t4n


                                                        Make sure that the checkbox for regular expressions is marked.



                                                        How it works:



                                                        The first step is to find a series of word characters, with w+, and capture the results in the variable 1 by wrapping parentheses around the expression:



                                                        (w+)


                                                        Next we search for a series of line ending characters, r and n, or CR and LF. Since Windows formatted files use both, we create a character class by wrapping these two characters in square brackets. The plus makes it search for one or more characters:



                                                        [rn]+


                                                        Finally, we repeat this 3 more times, storing each subsequent word in variables 2, 3, and 4. This makes our replace with expression simple. We just need to place tab characters, t, and a new line character, n, in the appropriate places for the formatting you need.







                                                        share|improve this answer














                                                        share|improve this answer



                                                        share|improve this answer








                                                        edited Apr 26 at 12:59

























                                                        answered Apr 26 at 4:33









                                                        Jason Wood

                                                        214




                                                        214



























                                                             

                                                            draft saved


                                                            draft discarded















































                                                             


                                                            draft saved


                                                            draft discarded














                                                            StackExchange.ready(
                                                            function ()
                                                            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f1028074%2fis-it-possible-with-gedit-or-the-command-line-to-modify-every-fourth-line-of-a-t%23new-answer', 'question_page');

                                                            );

                                                            Post as a guest













































































                                                            Popular posts from this blog

                                                            pylint3 and pip3 broken

                                                            Missing snmpget and snmpwalk

                                                            How to enroll fingerprints to Ubuntu 17.10 with VFS491