node exec awk command quotations - node.js

Using this pattern to pass a parameter in exec command:
const the_xml_file = 'pubmed22n1171.xml';
const the_command = "echo " + the_xml_file;
async function myBash() {
try {
const { stdout, stderr } = await exec( the_command );
console.log(stdout);
} catch (err){
console.error(err);
//console.log('stderr:', stderr);
};
};
However when the command is
const the_command = "awk 'BEGIN{splitno=15000; sn=splitno+1; out=FILENAME\"_\"int(c++/sn)+1\".xml\"} /<PubmedArticle/{f=1} f{print > out} /<\/PubmedArticle>/&&c%sn==0{close(out); f=0}' " + the_xml_file;
I get an error:
Error: Command failed: awk 'BEGIN{splitno=15000; sn=splitno+1; out=FILENAME"_"int(c++/sn)+1".xml"} /<PubmedArticle/{f=1} f{print > out} /</PubmedArticle>/&&c%sn==0{close(out); f=0}' pubmed22n1171.xml
awk: non-terminated regular expression &&c%sn==0{... at source line 1
context is
BEGIN{splitno=15000; sn=splitno+1; out=FILENAME"_"int(c++/sn)+1".xml"} /<PubmedArticle/{f=1} f{print > out} /</PubmedArticle>/&&c%sn==0{close(out); >>> f=0} <<<
Ive tested the awk command and it works from the console so I'm assuming this is a quotation mark issue. Any suggestions would be appreciated.

Related

Spawn command with redirection

Let say I have this command
somecli -s < "/path/to/file.txt"
How can I convert the above command to NodeJS spawn command ? I did something like this, but seems like it didn't pass the input.
spawn('somecli', ['-s', '<', '"/path/to/file.txt"'], { stdio: 'inherit'}).on('error', function (error) {
// something
});
I can use the exec command below and it's working, but I prefer if we can see the live output.
exec('somecli -s < "/path/to/file.txt"', (e, stdout, stderr) => {
// something
})
something like this should help
const { spawn } = require('child_process');
const fs = require('fs');
const writeStream = fs.createWriteStream("/path/to/file.txt");
const shell = spawn('somecli', ['-s']);
shell.stdout.pipe(writeStream);
To pass file input to command ( STDIN redirection )
$ somecli -s < /path/to/file.txt
We can do it something like this
spawn('somecli', ['-s'], {stdio: [fs.openSync('/path/to/file.txt', 'r'), process.stdout, process.stderr]});
To pass command output to file ( STDOUT redirection )
$ somecli -s > /path/to/file.txt
You may follow Ashish answer
let s = spawn('somecli', ['-s])
s.stdout.pipe(fs.createWriteStream('/path/to/file.txt'))

In Node.js, why does my spawn command produce an error?

When I run:
unzip -p /tmp/document.docx word/document.xml | sed -e 's/<\/w:p>/\\n/g; s/<[^>]\{1,\}>//g; s/[^[:print:]\n]\{1,\}//g'
It correctly extracts the text from my .docx file.
But when I try to wrap this in a Node.js program as follows:
const spawn = require("child_process").spawn;
const command = "unzip"; ;
const child = spawn("sh", ["-c", "unzip -p /tmp/document.docx word/document.xml | sed -e 's/<\/w:p>/\\n/g; s/<[^>]\{1,\}>//g; s/[^[:print:]\n]\{1,\}//g'"]);
const stdout = child.stdout;
const stderr = child.stderr;
const output = "";
stderr.on("data", function(data) {
console.error("error on stderr", data.toString());
});
stdout.on("data", function(data) {
output += data;
});
stdout.on("close", function(code) {
});
I get the following error message:
error on stderr sed: -e expression #1, char 10: unknown option to `s'
How do I fix this error?
When using a command line that way in your code, you have to think about the interpretation of the \ made by node.js and antislash the antislash. One for the node.js one for the sed command.
spawn("sh", ["-c", "unzip -p /tmp/document.docx word/document.xml | sed -e 's/<\\/w:p>/\\\\n/g; s/<[^>]\\{1,\\}>//g; s/[^[:print:]\\n]\\{1,\\}//g'"])
Look at here
#T.J Crowder
In JavaScript, the backslash has special meaning both in string
literals and in regular expressions. If you want an actual backslash
in the string or regex, you have to write two: \.

Japanese Transliteration in Node.js and Kakasi

I have written a little wrapper for Kakasi
that is like the following:
Kakasi.prototype.transliterate = function (data) {
var self = this;
return new Promise(function (resolve, reject) {
var args;
args = [
'-i',
'euc',
'-Ha',
'-Ka',
'-Ja',
'-Ea',
'-ka',
'-s',
'-iutf8',
'-outf8'
];
var kakasi = spawn(self._options.bin, args, {});
console.log( "echo \""+data+"\" | " + kakasi.spawnargs.join(' ') )
args = [
data
];
var echo = spawn('echo', args, {});
echo.stdout.pipe( kakasi.stdin );
var res='';
kakasi.stdout.on('data', function(_data) {
var data=new Buffer(_data,'utf-8').toString();
res+=data;
});
kakasi.stdout.on('end', function(_) {
return resolve(res);
});
kakasi.on('error', function(error) {
return reject(error);
});
if (self._options.debug) kakasi.stdout.pipe(process.stdout);
});
}//transliterate
This code basically does the following command
echo "退屈であくびばっかしていた毎日" | kakasi -i euc -Ha -Ka -Ja -Ea -ka -s -iutf8 -outf8
that outputs taikutsu deakubibakkashiteita mainichi
Problem is that the javascript is missing some output infact:
$ node transliterate.js
echo "退屈であくびばっかしていた毎日" | kakasi -i euc -Ha -Ka -Ja -Ea -ka -s -iutf8 -outf8
----------
deakubibakkashiteita
The input parameters are the same, but for some reason (encoding?) the child output to stdout is different.
The kakasi.js code is available here.
I think your dictionary loader causes this problem. You should flip the dictionaries as follows.
process.env.KANWADICTPATH = resolve('./data/kanwadict');
process.env.ITAIJIDICTPATH = resolve('./data/itaijidict');
instead of
process.env.KANWADICTPATH = resolve('./data/itaijidict');
process.env.ITAIJIDICTPATH = resolve('./data/kanwadict');

Spawn in nodejs for a unix command with spaces in parameters

I would like to execute the following command using nodejs Spawn on a Debian system :
/usr/bin/apt-get upgrade -s | tail -1 | cut -f1 -d' '
I want to use spawn and not exec because of future use of root only commands and i don't want to allow a full shell access (i will update the visudo file with correct commands)
Here is my code
const apt = spawn('/usr/bin/apt-get', ['upgrade', '-s']);
const tail = spawn('tail', ['-1']);
const cut = spawn('cut', ['-f1', '-d" "']);
apt.stdout.on('data', (data) => {
tail.stdin.write(data);
});
tail.stdout.on('data', (data) => {
cut.stdin.write(data);
});
cut.stdout.on('data', (data) => {
console.log(data.toString());
});
apt.stderr.on('data', (data) => {
console.log("apt stderr: ${data}");
});
tail.stderr.on('data', (data) => {
console.log("tail stderr: ${data}");
});
cut.stderr.on('data', (data) => {
console.log("cut stderr: ${data}");
});
apt.on('close', (code) => {
if (code !== 0) {
console.log("apt process exited with code ${code}");
}
});
tail.on('close', (code) => {
if (code !== 0) {
console.log("tail process exited with code ${code}");
}
});
cut.on('close', (code) => {
if (code !== 0) {
console.log("cut process exited with code ${code}");
}
});
res.status(200).json('');
Once executed i have an error because of the '-d" "' parameter that is not recognized. I try escaping the space with a double \ or split the parameter in both but still errors
It should just be:
const cut = spawn('cut', ['-f1', '-d ']);
No double quotes or backslash escapes -- those are for the use of the shell, not cut, and there's no shell here.
This makes dealing with unknown filenames (for your future use cases) particularly easy: When your strings are passed as arguments (to software that doesn't misuse them my running eval-equivalent code later), you don't need to quote, escape, sanitize, or otherwise modify them before they can be passed as data.
(That is to say -- when you tell your shell cut -f1 -d" ", the actual syscall it invokes to start that cut process, in C syntax, looks like execve("/usr/bin/cut", {"cut", "-f1", "-d ", NULL}, environ); the quotes were syntactic, consumed by the shell when it used them to make the decision that the space after the -d should be part of the same literal argument).

How to exec script to set iterm2 Badge from nodejs?

I get this bash script from Iterm2 official site.
printf "\e]1337;SetBadgeFormat=%s\a" $(echo "text" | base64)
I tried exec like bellow, there is no error, but failed to set iterm2 Badge
var exec = require('child_process').exec;
exec('printf "\e]1337;SetBadgeFormat=%s\a" $(echo "text" | base64)');
setBadgeFormat.js =>
#!/usr/bin/env node
var rawBadgeFormat = 'test'
var base64BadgeFormat = new Buffer(rawBadgeFormat).toString('base64')
var setBadgeFormatCmd = 'printf "\\e]1337;SetBadgeFormat=' + base64BadgeFormat + '\\a"'
require('child_process').exec(setBadgeFormatCmd, function(error, stdout, stderr) {
if (error) console.log(error);
process.stdout.write(stdout); // this line actually do the trick
process.stderr.write(stderr);
});

Resources