How to add a multi line string as value to key using node ?
I don't want to use emitter.
I want something like below code
Iphone:
blah ... blah \n
blah .... blah \n
I want to create the data similar to above programitically using a YAML::Node object.
Just set the string in your node:
YAML::Node node;
node["iphone"] = "blah ... blah \n blah .... blah \n"
std::cout << node;
If you're looking to have it output with multiple lines, instead of \n, you'll have to use an emitter; yaml-cpp doesn't support formatting output with basic node dumping. (Feel free to file an issue on the project page if you think it's worthwhile.)
Related
I want to change [%a/b] to [%a/c].
Basically, the same as Change path or refinement, but with file! instead:
I want to change the a/b inside a block to a/c
test: [a/b]
In this case, either change next test/1 'c or test/1/2: 'c works.
But not when test is a file!:
>> test: [%a/b]
== [%a/b]
>> test/1
== %a/b
>> test/1/2 ; can't access 2nd value
== %a/b/2
>> next first test ; not quite what you expect
== %/b
Trying to change it gives not something you'd expect:
>> change next test/1 'c
== %b
>> test
== [%acb]
You are confusing path! and file! series, they can look similar, but their nature are very different.
A path! is a collection of values (often word! values) separated by a slash symbol, a file! is a collection of char! values. Slash characters in file! series are just characters, so file! has no knowledge about any sub-structures. It has (mostly) the semantics of string! series, while path! has the semantics of a block! series.
Now that this is cleared, about the test/1/2 result, path notation on a file! series has a different behavior than on string!, it will do a smart concatenation instead of acting as an accessor. It's called smart because it will nicely handle extra slash characters present in left and right parts. For example:
>> file: %/index.html
== %/index.html
>> path: %www/
== %www/
>> path/file
== %www/file
>> path/:file
== %www/index.html
Same path notation rule applies to url! series too:
>> url: http://red-lang.org
== http://red-lang.org
>> url/index.html
== http://red-lang.org/index.html
>> file: %/index.html
== %/index.html
>> url/:file
== http://red-lang.org/index.html
So for changing the nested content of test: [%a/b], as file! behaves basically as string!, you can use any available method for strings to modify it. For example:
>> test: [%a/b]
== [%a/b]
>> change skip test/1 2 %c
== %""
>> test
== [%a/c]
>> change next find test/1 slash "d"
== %""
>> test
== [%a/d]
>> parse test/1 [thru slash change skip "e"]
== true
>> test
== [%a/e]
Files are string types and can be manipulated in the same way you'd modify a string. For example:
test: [%a/b]
replace test/1 %/b %/c
This is because file! is an any-string!, not any-array!
>> any-string? %a/c
== true
>> any-array? 'a/c
== true
So the directory separator '/' in a file! doesn't mean anything special with the action CHANGE. So 'a', '/', and 'b' in %a/b are treated the same way, and the interpreter isn't trying to parse it into a two segment file path [a b].
While for a path!, because it's an array, each component is a rebol value, and the interpreter knows that. For instance, 'bcd' in a/bcd will be seen as a whole (a word!), instead of three characters 'b', 'c' and 'd'.
I agree that the file! being an any-string! is not convenient.
Here is a maybe cumbersome solution, but suitable for directories treating them as files
test/1: to-file head change skip split-path test/1 1 %c
I want to use a one-liner to print a middle section of a file by using a state variable to indicate whether the current line is within the desired section of the file. But I am unable to initialize the state variable. Initialization is so simple, and I just cannot find what the problem is. Please help. Thanks.
The file is name testFile.txt and has the following lines:
section 0; state 0; not needed
= start section 1 =
state 1; needed
= end section 1 =
section 2; state 2; not needed
And my one-liner is
cat testFile.txt | perl6 -ne ' state $x = 0; say "$x--> "; if $_ ~~ m/ "start" / { $x=1; }; if $x == 1 { .say; }; if $_ ~~ m/ "end" / { $x = 2; }'
And the output showed that $x=0 is not doing initialization:
Use of uninitialized value $x of type Any in string context.
Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful.
in block at -e line 1
-->
Use of uninitialized value of type Any in numeric context
in block at -e line 1
Use of uninitialized value $x of type Any in string context.
Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful.
in block at -e line 1
-->
= start section 1 =
1-->
state 1; needed
1-->
= end section 1 =
2-->
2-->
This looks like a bug to me: Apparently, -n does not properly set up a lexical environment.
As a workaround, you can wrap the whole things in a block, eg by surrounding your code with do { ... } or even just { ... }.
Also note that depending on your use case, the whole thing can probably be simplified by using the flip-flop operator, eg
cat testFile.txt | perl6 -ne '.say if / "start" / ff / "end" /'
I have the following text...
BIOS Information
Manufacturer : Dell Inc.
Version : 2.5.2
Release Date : 01/28/2015
Firmware Information
Name : iDRAC7
Version : 2.21.21 (Build 12)
Firmware Information
Name : Lifecycle Controller 2
Version : 2.21.21.21
... which is piped into the following awk statement...
awk '{ if ($1" "$2 == "BIOS Information") var=$1} END { print var }'
This will output 'BIOS' in this case.
I want to look for 'BIOS Information' and then set the third field, two lines down, so in this case 'var' would equal '2.5.2'. Is there a way to do this with awk?
EDIT:
I tried the following:
awk ' BEGIN {
FS="[ \t]*:[ \t]*";
}
NF==1 {
sectname=$0;
}
NF==2 && $1 == "Version" && sectname="BIOS Information" {
bios_version=$2;
}
END {
print bios_version;
}'
Which gives me '2.21.21.21' with the above text. Can this be modified to give me the first 'Version" following "BIOS Information"?
Following script may be an overkill but it is robust in cases if you have multiple section names and/or order of fields is changed.
BEGIN {
FS="[ \t]*:[ \t]*";
}
NF==1 {
sectname=$0;
}
NF==2 && $1 == "Version" && sectname=="BIOS Information" {
bios_version=$2;
}
END {
print bios_version;
}
First, we set input field separator so that words are not separated into different fields. Next, we check whether current line is section name or a key-value pair. If it is section name, set sectname to section name. If it is a key-value pair and current section name is "BIOS Information" and key is "Version" then we set bios_version.
To answer the question as asked:
awk -v RS= '
/^BIOS Information\n/ {
for(i=1;i<=NF;++i) { if ($i=="Version") { var=$(i+2); exit } }
}
END { print var }
' file
-v RS= puts awk in paragraph mode, so that each run of non-empty lines becomes a single record.
/^BIOS Information\n/ then only matches a record (paragraph) whose first line equals "BIOS Information".
Each paragraph is internally still split into fields by any run of whitespace (awk's default behavior), so the for loop loops over all fields until it finds literal Version, assigns the 2nd field after it to a variable (because : is parsed as a separate field) and exits, at which point the variable value is printed in the END block.
Note: A more robust and complete way to extract the version number can be found in the update below (the field-looping approach here could yield false positives and also only ever reports the first (whitespace-separated) token of the version field).
Update, based on requirements that emerged later:
To act on each paragraph's version number and create individual variables:
awk -v RS= '
# Helper function that that returns the value of the specified field.
function getFieldValue(name) {
# Split the record into everything before and after "...\n<name> : "
# and the following \n; the 2nd element of the array thus created
# then contains the desired value.
split($0, tokens, "^.*\n" name "[[:blank:]]+:[[:blank:]]+|\n")
return tokens[2]
}
/^BIOS Information\n/ {
biosVer=getFieldValue("Version")
print "BIOS version = " biosVer
}
/^Firmware Information\n/ {
firmVer=getFieldValue("Version")
print "Firmware version (" getFieldValue("Name") ") = " firmVer
}
' file
With the sample input, this yields:
BIOS version = 2.5.2
Firmware version (iDRAC7) = 2.21.21 (Build 12)
Firmware version (Lifecycle Controller 2) = 2.21.21.21
Given:
$ echo "$txt"
BIOS Information
Manufacturer : Dell Inc.
Version : 2.5.2
Release Date : 01/28/2015
Firmware Information
Name : iDRAC7
Version : 2.21.21 (Build 12)
Firmware Information
Name : Lifecycle Controller 2
Version : 2.21.21.21
You can do:
$ echo "$txt" | awk '/^BIOS Information/{f=1; printf($0)} /^Version/ && f{f=0; printf(":%s\n", $3)}'
BIOS Information:2.5.2
Let's assume I have a notes field with new lines characters in it.
What solution is correct and what is the difference between them?
1
{
"notes" : "test test test \n line2"
}
2
{
"notes" : "test test test \\n line2"
}
Thank you
In the output below:
{
"notes" : "test test test \n line2"
}
a new line character has been escaped using \n.
On your UI, you probably want to show
test test test
line2
I am assuming that you are retrieving the json from a data store (perhaps MySQL). If yes please see this answer about escaping newline chars in MYSSQL and MySQL string literals
I have a template for an email that I've put in a localized strings file, and I'm loading the string with the NSLocalizedString macro.
I'd rather not make each line its own string with a unique key. In Objective-C, I can create a human-readable multiline string like so:
NSString *email = #"Hello %#,\n"
"\n"
"Check out %#.\n"
"\n"
"Sincerely,\n"
"\n"
"%#";
I tried to put that in a .strings file with:
"email" = "Hello %#,\n"
"\n"
"Check out %#.\n"
"\n"
"Sincerely,\n"
"\n"
"%#";
But I get the following error at build time:
CFPropertyListCreateFromXMLData(): Old-style plist parser: missing semicolon in dictionary.
email-template.strings: Unexpected character " at line 1
Command /Developer/Library/Xcode/Plug-ins/CoreBuildTasks.xcplugin/Contents/Resources/copystrings failed with exit code 1
I can concatenate it all together like this:
"email" = "Hello %#,\n\nCheck out %#.\n\nSincerely,\n\n%#";
But that will be a mess to maintain, particularly as the email gets longer.
Is there a way to do this in a localized strings file? I've already tried adding backslashes at the end of each line, to no avail.
Just use the new lines directly.
"email" = "Hello %#,
Check out %#.
Sincerely,
%#";