4
$\begingroup$

I am trying to do some text manipulation in Mathematica. After importing a text file (in.txt) as a string, how would you then output every other line? In the command line using awk for instance one would do

awk 'NR % 9 != 8' in.txt

However, after looking through the documentation Mathematica doesn't seem to have any current line number querying mechanism. Do you need to split the input string on every new line and then work with the list of strings? Or is Mathematica not the best choice for manipulating text?

$\endgroup$
  • $\begingroup$ There is a mistake in you awk's code: it should be awk 'NR % 2!=0' file.txt $\endgroup$ – SquareOne Sep 15 '15 at 14:32
8
$\begingroup$

You could fashion yourself a tool, for instance the following:

printlines[filename_, start_: 1, end_: All, every_: 1] := Module[
  {lines},
  lines = MapIndexed[
     {First@#2, #1} &,
     ReadList[filename, "String"]
    ];
  Grid[lines[[start ;; end ;; every]], Alignment -> {{Right, Left}}]
]

You can pass a filename to open, and option arguments to specify the first and last lines to print, and the "pitch" (i.e. printing every 2nd, 3rd, ... line). For instance:

file = "what's in a name.txt";
printlines[file]

Juliet's monologue

printlines[file, 6, 7]

only the punchline

printlines[file, 6, All, 3]

every three lines

$\endgroup$
1
$\begingroup$

The awk approach you gave as an example is fundamentally different to what you ask. With awk you do some text processing ON THE FLY (at the same time each line is read), it is not equivalent to 1/read ALL the text first, then 2/ do the filtering, processing on the whole text saved in memory. These involve completely different strategies.

You can actually do something similar to awk in Mathematica using Low level functions:

To read every other line on the fly, you can do for example:

(* Here is the way to create the dummy file, "file.txt", example I use in the test:
Table["Blabla # "<>ToString[i]<>"\n", {i, 10}]//StringJoin//Export["file.txt", #] &
*)


stream = OpenRead["file.txt"];

NestWhileList[
 (Skip[stream, Record]; Read[stream, Record])&,
 (Read[stream, Record]),
 # =!= EndOfFile &,
 1, Infinity, -1]

Close[stream]

{"Blabla # 1", "Blabla # 3", "Blabla # 5", "Blabla # 7", "Blabla # 9"}

In case you don't know, it is also possible to run directly from Mathematica the awk's code (or some other external command) and retrieve the result, for example here:

ReadList["!awk 'NR % 2!=0' file.txt", String]

{"Blabla # 1", "Blabla # 3", "Blabla # 5", "Blabla # 7", "Blabla # 9"}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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