I have some log format with entries like this:
log_entry_no1 := "2021-11-03 7:7:51 hal9000 evil_app heartbeat C99 I am sorry Dave"
Those "fields" are separated by space except the last one called message which is just log data and can contain spaces.
My question is. Is there better way to process those entries without first splitting whole sentence and then join'ing that last part (message) with less overhead using go?
type LogData struct {
d Date // yyyy-mm-dd Mandatory
t Time // hh:mm:ss Mandatory
hostname string // Mandatory
app_id string // Mandatory
etype string // enum based string Mandatory
level string // Optional base on etype
message string // Mandatory
}
log_fields := strings.Split(log_entry_no1, " ")
var log_data = LogData{}
log_data.d = parseTime(log_entry_no1[0])
log_data.t = parseTime(log_entry_no1[1])
//...
if log_fields[4] == "heartbeat" {
log_data.level = log_fields[5]
log_data.message = strings.Join(log_fields[6:], " ")
} else {
log_data.message = strings.Join(log_fields[5:], " ")
}
Use strings.SplitN.
func SplitN(s, sep string, n int) []string
The docs say if n is greater than zero: it returns at most n substrings; the last substring will be the unsplit remainder.
Related
Go noob here, and all I want to do is use the time format constants list https://golang.org/src/time/format.go that are mentioned in 3 posts here on SO (https://stackoverflow.com/a/20234207 https://stackoverflow.com/a/14106561 https://stackoverflow.com/a/20234207). None of which including the docs (at least that I can tell) have an example of how to use them.
I would expect this to work (but it clearly does not):
t := time.Now()
log.Println(t.stdHour12())
Can you please tell me how to get only the hour (in 12 hour time) for a given time t (ex: 10 from 2021-03-09 22:45:04.009063861 -0500 EST)?
const (
stdLongMonth = "January"
stdMonth = "Jan"
stdNumMonth = "1"
stdZeroMonth = "01"
stdLongWeekDay = "Monday"
stdWeekDay = "Mon"
stdDay = "2"
stdUnderDay = "_2"
stdZeroDay = "02"
stdHour = "15"
stdHour12 = "3"
stdZeroHour12 = "03"
stdMinute = "4"
stdZeroMinute = "04"
stdSecond = "5"
stdZeroSecond = "05"
stdLongYear = "2006"
stdYear = "06"
stdPM = "PM"
stdpm = "pm"
stdTZ = "MST"
stdISO8601TZ = "Z0700" // prints Z for UTC
stdISO8601ColonTZ = "Z07:00" // prints Z for UTC
stdNumTZ = "-0700" // always numeric
stdNumShortTZ = "-07" // always numeric
stdNumColonTZ = "-07:00" // always numeric
)
Thanks in advance!
EDIT: From the answers received so far, I see that I cannot use the constants above to achieve what I want so I changed the wording of this question to specifically ask to return the hour (and just the hour) for a given time.
The Time object specifies the full date and time. You can extract just the time, if you like:
func main() {
t := time.Now()
fmt.Println(t.Format(time.Kitchen))
}
time.Kitchen is defined in the time package as Kitchen = "3:04PM"
If you want to understand how the format is interpreted, read this piece of documentation carefully
If you just need the hour, call the Hour() method on a Time object. If you want it in 12-hour format, you can just do modulo 12:
func main() {
t := time.Now()
fmt.Println(t.Hour())
fmt.Println(t.Hour() % 12)
}
These are constants representing tokens used internally by formatting code in time package (note they start with lower letter so they aren't exported and you can't even use them outside time package).
If you want to come up with your own format in Go (for both parsing and output) you simply define it using these tokens "as example" and Format() will parse it and apply that format (if valid) to itself.
const (
MyLayout = "3"
)
func main() {
t := time.Now()
fmt.Println(t.Format(MyLayout))
}
Available tokens are listed for example here.
It causes discomfort when you can do that:
val string = " abc "
val integer = 8
val result = string + integer
and can't do:
val result = integer + string
It has hidden meaning or it's an omission?
Kotlin is static typed language and in basicly you can't add String to Integer. But there are possible to overload operators, so we can now.
In case when we want add any object to string, it's clear: every object can be implicitly converted to String (Any#toString())
But in case of Int + smthg it's not so clear, so only Int + kotlin.Number is defined in standard library.
I suggest to use string interpolation:
val result = "${integer}${string}"
Or define own overloaded plus operator:
operator fun Int.plus(string: String): String = string + this
I just noticed that the latest beta of Xcode (7.1) has changed the signature for the print function in Swift.
The new syntax is:
public func print(items: Any..., separator: String = default, terminator: String = default)
Anybody knows what this default thing is? How do you specify the default value, not just the fact that it has one?
The default in the function signature means that it has a default value and you don't have to pass a parameter.
func add(a: Int = 0, b: Int = 0) -> Int {
return a + b
}
// "normal" function call
add(2, b: 4) // 6
// no specified parameters at all
add() // 0; both a and b default to 0
// one parameter specified
// a has no external name since it is the first parameter
add(3) // 3; b defaults to 0
// b has an external name since it is not the first parameter
add(b: 4) // 4; a defaults to 0
In case of the print function separator defaults to " " and terminator to "\n".
There are 4 way to call it:
struct SomeItem {}
print(SomeItem(), SomeItem())
print(SomeItem(), SomeItem(), separator: "_")
print(SomeItem(), SomeItem(), terminator: " :) \n")
print(SomeItem(), SomeItem(), separator: "_", terminator: " :) \n")
Prints:
SomeItem() SomeItem()
SomeItem()_SomeItem()
SomeItem() SomeItem() :)
SomeItem()_SomeItem() :)
the default separator is a single space, and the default terminator is a newline
to use a different value for either of these, simply pass the desired value as an argument when you call the function - e.g.:
print("first", "second", separator: "-", terminator: "...")
print("third")
// => "first-second...third"
Hello i would like to create a app that changes characters into binary code and i was wondering if there is a way to add multiple stringByReplacingOccurrencesOfString on one String or if i should take another approach to this "Problem".
Here is what i have so far
func textToBinary(theString: String) -> String {
return theString.stringByReplacingOccurrencesOfString("a",
withString: "01100001")
}
textArea.text = textToBinary(lettersCombined)
// lettersCombined is the string that i want to turn into BinaryCode.
Try this:
func textToBinary(theString : String, radix : Int = 2) -> String {
var result = ""
for c in theString.unicodeScalars {
result += String(c.value, radix: radix) + " "
}
return result
}
println(textToBinary("a"))
println(textToBinary("abc", radix: 10))
println(textToBinary("€20", radix: 16))
println(textToBinary("😄"))
(The last one is a smiley face but somehow my browser can't display it).
Edit: if you want to pad your strings to 8-character long, try this:
let str = "00000000" + String(c.value, radix: radix)
result += str.substringFromIndex(advance(str.startIndex, str.characters.count - 8)) + " "
The first line adds eight 0 the left of your string. The second line takes the last 8 characters from the padded string.
I apologize for creating a similar thread to many that are out there now, but I mainly wanted to also get some insight on some methods.
I have a list of Strings (could be just 1 or over a 1000)
Format = XXX-XXXXX-XX where each one is alphanumeric
I am trying to generate a unique string (currently 18 in length but probably could be longer ensuring not to maximize file length or path length) that I could reproduce if I have that same list. Order doesn't matter; although I may be interested if its easier to restrict the order as well.
My current Java code is follows (which failed today, hence why I am here):
public String createOutputFileName(ArrayList alInput, EnumFPFunction efpf, boolean pHeaders) {
/* create file name based on input list */
String sFileName = "";
long partNum = 0;
for (String sGPN : alInput) {
sGPN = sGPN.replaceAll("-", ""); //remove dashes
partNum += Long.parseLong(sGPN, 36); //(base 36)
}
sFileName = Long.toString(partNum);
if (sFileName.length() > 19) {
sFileName.substring(0, 18); //Max length of 19
}
return alInput;
}
So obviously just adding them did not work out so well I found out (also think I should take last 18 digits and not first 18)
Are there any good methods out there (possibly CRC related) that would work?
To assist with my key creation:
The first 3 characters are almost always numeric and would probably have many duplicate (out of 100, there may only be 10 different starting numbers)
These characters are not allowed - I,O
There will never be a character then a number in the last two alphachar subset.
I would use the system time. Here's how you might do it in Java:
public String createOutputFileName() {
long mills = System.currentTimeMillis();
long nanos = System.nanoTime();
return mills + " " + nanos;
}
If you want to add some information about the items and their part numbers, you can, of course!
======== EDIT: "What do I mean by batch object" =========
class Batch {
ArrayList<Item> itemsToProcess;
String inputFilename; // input to external process
boolean processingFinished;
public Batch(ArrayList<Item> itemsToProcess) {
this.itemsToProcess = itemsToProcess;
inputFilename = null;
processingFinished = false;
}
public void processWithExternal() {
if(inputFilename != null || processingFinished) {
throw new IllegalStateException("Cannot initiate process more than once!");
}
String base = System.currentTimeMillis() + " " + System.nanoTime();
this.inputFilename = base + "_input";
writeItemsToFile();
// however you build your process, do it here
Process p = new ProcessBuilder("myProcess","myargs", inputFilename);
p.start();
p.waitFor();
processingFinished = true;
}
private void writeItemsToFile() {
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(inputFilename)));
int flushcount = 0;
for(Item item : itemsToProcess) {
String output = item.getFileRepresentation();
out.println(output);
if(++flushcount % 10 == 0) out.flush();
}
out.flush();
out.close();
}
}
In addition to GlowCoder's response, I have thought of another "decent one" that would work.
Instead of just adding the list in base 36, I would do two separate things to the same list.
In this case, since there is no way for negative or decimal numbers, adding every number and multiplying every number separately and concatenating these base36 number strings isn't a bad way either.
In my case, I would take the last nine digits of the added number and last nine of the multiplied number. This would eliminate my previous errors and make it quite robust. It obviously is still possible for errors once overflow starts occurring, but could also work in this case. Extending the allowable string length would make it more robust as well.
Sample code:
public String createOutputFileName(ArrayList alInput, EnumFPFunction efpf, boolean pHeaders) {
/* create file name based on input list */
String sFileName1 = "";
String sFileName2 = "";
long partNum1 = 0; // Starting point for addition
long partNum2 = 1; // Starting point for multiplication
for (String sGPN : alInput) {
//remove dashes
sGPN = sGPN.replaceAll("-", "");
partNum1 += Long.parseLong(sGPN, 36); //(base 36)
partNum2 *= Long.parseLong(sGPN, 36); //(base 36)
}
// Initial strings
sFileName1 = "000000000" + Long.toString(partNum1, 36); // base 36
sFileName2 = "000000000" + Long.toString(partNum2, 36); // base 36
// Cropped strings
sFileName1 = sFileName1.substring(sFileName1.length()-9, sFileName1.length());
sFileName2 = sFileName2.substring(sFileName2.length()-9, sFileName2.length());
return sFileName1 + sFileName2;
}