io.popen():lines() ignores first non-empty line - lua

I have a shell script that has an output like this:
1
Space Cruise (Title)
Ben Prunty Music
FTL
46.4
Now I want to map the lines to an array like this:
mymplayer = { track="", title="", artist="", album="", time="" }
So I'm using io.popen() like this (for testing purposes):
function get_data()
local fh = io.popen("bin/mplayerout.sh")
for l in fh:lines() do print(l) end
end
The problem is that this has the following output:
Space Cruise (Title)
Ben Prunty Music
FTL
46.4
Now, if I make my script's output start with a newline, the output is like this:
<empty line>
Space Cruise (Title)
Ben Prunty Music
FTL
46.4
What am I doing wrong?

Alright, I found the issue. When doing the same in Python, I got the first line - but as 3281 null bytes ('\x00') followed by '\x02\n'.
Looks like the problem is in the script...

It could be that the first line of output from mplayerout.sh ends in a carriage return ("\r") while the others end in newlines ("\n" or "\r\n".)
Then the initial "1" would still be in the output, but the "\r" will cause the terminal to overwrite it with the following characters.
You can see this by using print(string.format("%q", l)). If there is a "\r" embedded in the first line, the output will be:
"1\rSpace Cruise (Title)"
"Ben Prunty Music"
"FTL"
"46.4"

Related

Grep lines for multiple words and the line ending, and then replace line ending if matched

I need to grep a long text file for lines that contains multiple possible words and also end in "=1", and then replace the line with the same text except change the "=1" to "=0".
I'm using BBEdit.
So far I have this to find lines that contains the desired match that also ends with 1:
^(.*test|.*disabled|.*inactive|.*server).*(=1)
I'm unable to do the replacement successfully though.
Here are some example lines of text from the file:
OU>2020,OU>Disabled Accounts,DC>net,DC>example,DC>com=1
OU>Distribution Groups,DC>net,DC>example,DC>com=1
OU>Exchange Servers,DC>net,DC>example,DC>com=1
CN>Users,DC>net,DC>example,DC>com=1
OU>Test Servers,OU>Servers,OU>ABC,DC>net,DC>example,DC>com=1
As an example, the first line above would have its =1 changed to =0 like:
OU>2020,OU>Disabled Accounts,DC>net,DC>example,DC>com=0
Other matches would follow that pattern.
After playing around with it more, this seems to work:
Find:
(^.*(test|disable|inactive|server).*)(=1)$
Replace:
\1=0

Remove two lines using sed

I'm writing a script which can parse an HTML document. I would like to remove two lines, how does sed work with newlines? I tried
sed 's/<!DOCTYPE.*\n<h1.*/<newstring>/g'
which didn't work. I tried this statement but it removes the whole document because it seems to remove all newlines:
sed ':a;N;$!ba;s/<!DOCTYPE.*\n<h1.*\n<b.*/<newstring>/g'
Any ideas? Maybe I should work with awk?
For the simple task of removing two lines if each matches some pattern, all you need to do is:
sed '/<!DOCTYPE.*/{N;/\n<h1.*/d}'
This uses an address matching the first line you want to delete. When the address matches, it executes:
Next - append the next line to the current pattern-space (including \n)
Then, it matches on an address for the contents of the second line (following \n). If that works it executes:
delete - discard current input and start reading next unread line
If d isn't executed, then both lines will print by default and execution will continue as normal.
To adjust this for three lines, you need only use N again. If you want to pull in multiple lines until some delimiter is reached, you can use a line-pump, which looks something like this:
/<!DOCTYPE.*/{
:pump
N
/some-regex-to-stop-pump/!b pump
/regex-which-indicates-we-should-delete/d
}
However, writing a full XML parser in sed or awk is a Herculean task and you're likely better off using an existing solution.
If an xml parsing tool is definitely not an option, awk maybe an option:
awk '/<!DOCTYPE/ { lne=NR+1;next } NR==lne && /<h1/ { next }1' file
When we encounter a line with "<!DOCTYPE" set the variable lne to the line number + 1 (NR+1) and then skip to the next line. Then when the line is equal to lne (NR==lne) and the line contains "<h1", skip to the next line. Print all other lines by using 1.
My solution for a document like this:
<b>...
<first...
<second...
<third...
<a ...
this awk command works well:
awk -v RS='<first[^\n]*\n<second[^\n]*\n<third[^\n]*\n' '{printf "%s", $0}'
that's all.
This might work for you (GNU sed):
sed 'N;/<!DOCTYPE.*\n<h1.*/d;P;D' file
Append the following line and if the pattern matches both lines in the pattern space delete them.
Otherwise, print then delete the first of the two lines and repeat.
To replace the two lines with another string, use:
sed 'N;s/<!DOCTYPE.*\n<h1.*/another string/;P;D'

SPSS print a statement to the ouput window

What syntax do I use to print "hello world" in the output window?
I simply want to specify the text in the syntax and have it appear in the output.
You need the title command:
title 'this is my text'.
Note that the title can be up to 256 bytes long.
Alternatively, you could use ECHO also. ECHO is useful for debugging macro variable assignements where as TITLE is useful for neat/organised presentation of your tables with intension to perhaps export output results.
If you want to write arbitrary text in its own block in the Viewer rather than having it stuck in a log block, use the TEXT extension command (Utilities > Create text output). You can even include html markup in the text.
If you don't have this extension installed, you can install it from the Utilities menu in Statistics 22 or 23 or the Extensions menu in V24.
example:
TEXT "The following output is very important!"
/OUTLINE HEADING="Comment" TITLE="Comment".
Outfile here is used in an ambiguous way. The prior two answers (the TITLE and ECHO commands) simply print something to the output window. One additional way to print to the output window is the PRINT command.
DATA LIST FREE / X.
BEGIN DATA
1
2
END DATA.
PRINT /'Hello World'.
EXECUTE.
If you do that set of syntax you will actually see that 'Hello World' is printed twice -- one for each record in the dataset. So one way to only print one line is to wrap it in a DO IF statement and only select the first row of data.
DO IF $casenum=1.
PRINT /'Hello World'.
END IF.
EXECUTE.
Now how is this any different than the prior two commands? Besides aesthetic looks in the output window, PRINT allows you to save an actual text file of the results via the OUTFILE parameter, which is something neither of the prior two commands allows.
DO IF $casenum=1.
PRINT OUTFILE='C:\Users\Your Name\Desktop\Hello.txt' /'Hello World'.
END IF.
EXECUTE.

using the newline character on windows

I've been having problems with the ~n in erlang, been trying for 2 days to write a list of data to a file, io:format(file, "~s~n", [X]).
of course i have tried using map and foreach to iterate through the list but still i am getting everything on 1 line instead of a newline character. the list is a list of lines read from a different file. This is a windows OS.
am I missing something? is there some alternative for doing this on windows? I've been reading many tutorials and asked here for help before but I'm beginning to think there is no solution for me :/ some very simple task in any other language, even haskell can do it.
I can print the list to the console and it will appear just as the text i read. but when i write this list to a file it appears all in 1 line. so:
blah
blah
blah
becomes
blah blah blah
And i cant get around this :(
Windows newlines are \r\n (carraige-return and newline).
Try:
io:format(File, "~s\r\n", [X]).
So assuming you have (in your example):
Data = ["blah", "blah", "blah"].
Then:
io:format(File, "~s\r\n", [string:join(Data, "\r\n")]).
will do what you want on Windows.
Frankly "~n" is supposed to be platform-dependent, but it isn't working for my version of Erlang, so the "\r\n" is necessary, i.e.
io:format(File, "~s~n", [string:join(Data, "\n")]).
should work, but doesn't.

GNU-M4: Strip empty lines

How can I strip empty lines (surplus empy lines) from an input file using M4?
I know I can append dnl to the end of each line of my script to suppress the newline output, but the blank lines I mean are not in my script, but in a data file that is included (where I am not supposed to put dnl's).
I tried something like that:
define(`
',`')
(replace a new-line by nothing)
But it didn't work.
Thanks.
I use divert() around my definitions :
divert(-1) will suppress the output
divert(0) will restore the output
Eg:
divert(-1)dnl output supressed starting here
define(..)
define(..)
divert(0)dnl normal output starting here
use_my_definitions()...
I understand your problem to be a data file with extra line breaks, meaning that where you want to have the pattern data<NL>moredata you have things like data<NL><NL>moredata.
Here's a sample to cut/paste onto your command line that uses here documents to generate a data set and runs an m4 script to remove the breaks in the data set. You can see the patsubst command replaces every instance of one or more newlines in sequence (<NL><NL>*) with exactly one newline.
cat > data << -----
1, 2
3, 4
5, 6
7, 8
9, 10
11, 12
e
-----
m4 << "-----"
define(`rmbreaks', `patsubst(`$*', `
*', `
')')dnl
rmbreaks(include(data))dnl
-----

Resources