Is it possible with Gedit or the command line to modify every fourth line of a text file?
![Creative The name of the picture](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO9GURib1T8z7lCwjOGLQaGtrueEthgQ8LO42ZX8cOfTqDK4jvDDpKkLFwf2J49kYCMNW7d4ABih_XCb_2UXdq5fPJDkoyg7-8g_YfRUot-XnaXkNYycsNp7lA5_TW9td0FFpLQ2APzKcZ/s1600/1.jpg)
![Creative The name of the picture](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYQ0N5W1qAOxLP7t7iOM6O6AzbZnkXUy16s7P_CWfOb5UbTQY_aDsc727chyphenhyphen5W4IppVNernMMQeaUFTB_rFzAd95_CDt-tnwN-nBx6JyUp2duGjPaL5-VgNO41AVsA_vu30EJcipdDG409/s400/Clash+Royale+CLAN+TAG%2523URR8PPP.png)
up vote
11
down vote
favorite
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:
Just for reference, the desired result should look like this:
command-line libreoffice gedit
add a comment |Â
up vote
11
down vote
favorite
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:
Just for reference, the desired result should look like this:
command-line libreoffice gedit
add a comment |Â
up vote
11
down vote
favorite
up vote
11
down vote
favorite
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:
Just for reference, the desired result should look like this:
command-line libreoffice gedit
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:
Just for reference, the desired result should look like this:
command-line libreoffice gedit
edited Apr 25 at 12:49
asked Apr 25 at 12:00
![](https://i.stack.imgur.com/nzyQw.png?s=32&g=1)
![](https://i.stack.imgur.com/nzyQw.png?s=32&g=1)
Questioner
1,4382480146
1,4382480146
add a comment |Â
add a comment |Â
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 :
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).
1
A note about Windows-style line endings: the standard tools to convert between them and Unix-style aredos2unix
andunix2dos
.
â David Foerster
Apr 26 at 10:50
add a comment |Â
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
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
add a comment |Â
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.
add a comment |Â
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 n
ewline 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.)
add a comment |Â
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/ $//'
add a comment |Â
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.
1
This isn't portable to POSIX compatible shells in general, because the$'
'
form of quoting is not required by POSIX. For example, indash
(which providessh
by default on Ubuntu), runningprintf '%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 usingread -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 doprintf '%st%st%st%sn' "$one" "$two" "$three" "$four"
â terdonâ¦
Apr 26 at 8:59
add a comment |Â
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
add a comment |Â
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.
add a comment |Â
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 :
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).
1
A note about Windows-style line endings: the standard tools to convert between them and Unix-style aredos2unix
andunix2dos
.
â David Foerster
Apr 26 at 10:50
add a comment |Â
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 :
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).
1
A note about Windows-style line endings: the standard tools to convert between them and Unix-style aredos2unix
andunix2dos
.
â David Foerster
Apr 26 at 10:50
add a comment |Â
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 :
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).
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 :
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).
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 aredos2unix
andunix2dos
.
â David Foerster
Apr 26 at 10:50
add a comment |Â
1
A note about Windows-style line endings: the standard tools to convert between them and Unix-style aredos2unix
andunix2dos
.
â 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
add a comment |Â
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
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
add a comment |Â
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
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
add a comment |Â
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
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
answered Apr 25 at 12:19
![](https://i.stack.imgur.com/m8DYH.jpg?s=32&g=1)
![](https://i.stack.imgur.com/m8DYH.jpg?s=32&g=1)
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
add a comment |Â
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
add a comment |Â
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.
add a comment |Â
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.
add a comment |Â
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.
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.
edited Apr 25 at 18:10
Eliah Kagan
79.4k20221359
79.4k20221359
answered Apr 25 at 18:07
arauk
311
311
add a comment |Â
add a comment |Â
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 n
ewline 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.)
add a comment |Â
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 n
ewline 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.)
add a comment |Â
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 n
ewline 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.)
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 n
ewline 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.)
edited Apr 26 at 8:05
answered Apr 26 at 4:59
ñÃÂsýù÷
23.2k2191152
23.2k2191152
add a comment |Â
add a comment |Â
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/ $//'
add a comment |Â
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/ $//'
add a comment |Â
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/ $//'
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/ $//'
edited Apr 26 at 8:39
![](https://i.stack.imgur.com/8CW8e.png?s=32&g=1)
![](https://i.stack.imgur.com/8CW8e.png?s=32&g=1)
Zanna
48k13119227
48k13119227
answered Apr 25 at 12:26
![](https://lh5.googleusercontent.com/-nCZDwgCu_zg/AAAAAAAAAAI/AAAAAAAAAak/_iqVlL0H0qs/photo.jpg?sz=32)
![](https://lh5.googleusercontent.com/-nCZDwgCu_zg/AAAAAAAAAAI/AAAAAAAAAak/_iqVlL0H0qs/photo.jpg?sz=32)
spaceman117X
1647
1647
add a comment |Â
add a comment |Â
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.
1
This isn't portable to POSIX compatible shells in general, because the$'
'
form of quoting is not required by POSIX. For example, indash
(which providessh
by default on Ubuntu), runningprintf '%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 usingread -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 doprintf '%st%st%st%sn' "$one" "$two" "$three" "$four"
â terdonâ¦
Apr 26 at 8:59
add a comment |Â
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.
1
This isn't portable to POSIX compatible shells in general, because the$'
'
form of quoting is not required by POSIX. For example, indash
(which providessh
by default on Ubuntu), runningprintf '%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 usingread -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 doprintf '%st%st%st%sn' "$one" "$two" "$three" "$four"
â terdonâ¦
Apr 26 at 8:59
add a comment |Â
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.
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.
edited Apr 25 at 17:48
![](https://i.stack.imgur.com/9L8vd.png?s=32&g=1)
![](https://i.stack.imgur.com/9L8vd.png?s=32&g=1)
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, indash
(which providessh
by default on Ubuntu), runningprintf '%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 usingread -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 doprintf '%st%st%st%sn' "$one" "$two" "$three" "$four"
â terdonâ¦
Apr 26 at 8:59
add a comment |Â
1
This isn't portable to POSIX compatible shells in general, because the$'
'
form of quoting is not required by POSIX. For example, indash
(which providessh
by default on Ubuntu), runningprintf '%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 usingread -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 doprintf '%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
add a comment |Â
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
add a comment |Â
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
add a comment |Â
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
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
answered Apr 25 at 22:10
rackandboneman
24316
24316
add a comment |Â
add a comment |Â
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.
add a comment |Â
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.
add a comment |Â
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.
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.
edited Apr 26 at 12:59
answered Apr 26 at 4:33
![](https://lh3.googleusercontent.com/-XdUIqdMkCWA/AAAAAAAAAAI/AAAAAAAAAAA/4252rscbv5M/photo.jpg?sz=32)
![](https://lh3.googleusercontent.com/-XdUIqdMkCWA/AAAAAAAAAAI/AAAAAAAAAAA/4252rscbv5M/photo.jpg?sz=32)
Jason Wood
214
214
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password