Modify date format in-place through `sed` command
Solution 1
If you have access to GNU date
(the default on Linux systems), you can do:
$ sed -E 's/(.*)-([a-z]+)(.+)/\2\3-\1/i' file |
while read d; do date -d "$d" +%d/%m/%y; done
24/12/16
24/12/16
That changes lines like 2016-Dec-24
to Dec-24-2016
(a format that GNU date
can understand), leaves lines like 2016-12-24
(a format GNU date already understands) alone, and then passes each line as an input date string to date
. It doesn't do it in-place and it doesn't use sed -i
but is almost certainly the simplest approach.
If you really need to do it using sed
, you could make a list of all months and corresponding numbers:
$ for m in {1..12}; do printf '%s %s\n' "$m" $(date -d "$m/1/2016" +%b); done
1 Jan
2 Feb
3 Mar
4 Apr
5 May
6 Jun
7 Jul
8 Aug
9 Sep
10 Oct
11 Nov
12 Dec
Save that as months
and then iterate over it to modify your file:
while read num mon; do
sed -Ei "s/$mon/$num/; s#(.*)-(.*)-(.*)#\3/\2/\1#" file
done < months
Or, if your sed implementation needs separate -e
:
while read num mon; do
sed -i -e "s/$mon/$num/" -Ee 's#(.*)-(.*)-(.*)#\3/\2/\1#' file
done < months
The first substitution will replace all alphabetical month names with their corresponding number and the second moves things around to get your desired format.
Solution 2
The only thing I see wrong regex-wise is that in basic (BRE) mode, |
is literal - you need \|
to make it a logical OR i.e. \(01\|Jan\)
and so on.
If your version supports -e
then I don't see any good reason to make multiple calls to sed
- you can just chain the -e <expr1> -e <expr2> ...
in a single call. So
sed -i \
-e 's/\([0-9]\{4\}\)-\(01\|Jan\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
-e 's/\([0-9]\{4\}\)-\(02\|Feb\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
-e 's/\([0-9]\{4\}\)-\(03\|Mar\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
-e 's/\([0-9]\{4\}\)-\(04\|Apr\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
-e 's/\([0-9]\{4\}\)-\(05\|May\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
-e 's/\([0-9]\{4\}\)-\(06\|Jun\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
-e 's/\([0-9]\{4\}\)-\(07\|Jul\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
-e 's/\([0-9]\{4\}\)-\(08\|Aug\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
-e 's/\([0-9]\{4\}\)-\(09\|Sep\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
-e 's/\([0-9]\{4\}\)-\(10\|Oct\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
-e 's/\([0-9]\{4\}\)-\(11\|Nov\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
-e 's/\([0-9]\{4\}\)-\(12\|Dec\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
However there are more elegant ways to do this - for example in perl using strptime
and strftime
functions (provided by the Time::Piece
module for example):
perl -i -MTime::Piece -pe '
s|\d{4}-\d\d-\d\d?|Time::Piece->strptime($&, "%Y-%m-%d")->strftime("%Y/%m/%d")|ge;
s|\d{4}-...-\d\d?|Time::Piece->strptime($&, "%Y-%b-%d")->strftime("%Y/%m/%d")|ge;
' file
ghiboz
Updated on September 18, 2022Comments
-
ghiboz over 1 year
I have this problem:
I create in unity a dll with this code:
public bool PackScripts(string dllPath, string[] scripts) { try { CodeDomProvider cc = CodeDomProvider.CreateProvider("CSharp"); CompilerParameters cp = new CompilerParameters(); var pf = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFiles); cp.ReferencedAssemblies.Add(string.Format(@"{0}\Unity\Editor\Data\Managed\UnityEngine.dll", pf)); cp.GenerateExecutable = false; //generate executable cp.OutputAssembly = dllPath; CompilerResults cr = cc.CompileAssemblyFromFile(cp, scripts); return cr.Errors.Count == 0; } catch { return false; } }
and works fine: if I create a solution with visual studio, include the dll created works fine!
but my goal is to load this dll dynamically.. to do this I use this code:
var assembly = System.Reflection.Assembly.Load("packScripts.dll");
and here appears this error:
FileNotFoundException: Could not load file or assembly 'C:/Users/Administrator/Documents/Unity/BundlesLoader/Assets/packscripts.dll' or one of its dependencies. The system cannot find the file specified. System.AppDomain.Load (System.String assemblyString, System.Security.Policy.Evidence assemblySecurity, Boolean refonly) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/AppDomain.cs:746) System.AppDomain.Load (System.String assemblyString) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/AppDomain.cs:728) (wrapper remoting-invoke-with-check) System.AppDomain:Load (string) System.Reflection.Assembly.Load (System.String assemblyString) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/Assembly.cs:576) Loader+<LoadBundle>c__Iterator0.MoveNext () (at Assets/Scripts/Loader.cs:94)
Also if I create a new solution and try to use the same code, it gives the same error.. any ideas?
thanks in advance!
-
Michael Vehrs over 7 yearsOf course, it is possible. What have you tried so far?
-
Alina Gorgovan over 7 yearsI've edited the question and added an input example, sorry for the misunderstanding.
-
-
Michael Vehrs over 7 yearsUsing
date
in a loop like that is inefficient. Usedate -f
instead. -
smw over 7 years@don_crissti I'd kind of assumed the intent was to eventually replace the
\2
backreference with the corresponding numeric month, as per the original question. That's why I left the OP's basic format as-is.