Just trying to delete lines of several .txt files - but keep getting SED error - sed

So, I am trying to delete the first 23 lines of many .txt files. This is what I am currently doing:
sed -i -e 1,23d * .txt
but it gives me a weird error:
sed: 1: "1,23": command expected
I have no idea what to do. _

Like this:
sed -i -e '1,23d' *.txt
# ^ mandatory 'd'
# ^
# no space between * and .txt

The original question (before editing) showed:
sed -i -e 1,23d * .txt
but it gives me a weird error:
sed: Applications: in-place editing only works for regular files
The space between * and .txt was a mistake, but is an explanation of the weird error: It looks for all files as well as for the hidden file .txt.
Linux considers the directory Application as a file, but sed does not work on files.
The directory Application suggests that the files might come from Windows.
Another question is why echo *.txt don't show the txt files Mia was expecting. A logical explanation is that the files originated from Windows and Mia doesn't know that Linux is case sensitive. Files like A.TXT and b.Txt don't match *.txt.
When all txt files end with TXT, you can do
sed -i -e '1,23d' *.TXT
When you have a mix of upper- and lower case, the easiest way is
sed -i -e '1,23d' *.[tT][xX][tT]

Related

Bash Script to append for specific file extensions in a directory

How do I prepends a special character in front of all the lines in all .txt files in my directory? Im new to writing bash scripts and having trouble doing this. I only know of using the grep function but thats only to search for keyword.
For now, I have this,
sed -i 's/^/#/' Machine1.txt
However, this is only for that specific .txt file. I want to do this for all files with a .txt extension in my directory. There are other extensions like .tar, .rpm, .sh files which I want to ignore. Thank you!
Just give a wildcard filename argument.
sed -i 's/^/#/' *.txt
you can use for loop.
For example
cd your_folder
for f in *.txt; do
sed -i 's/^/#/' "$f";
done

Remove space between a keyword and paranthesis

I have nearly 300 files in 60 folders .
As per the C++ coding guidelines, I need to replace below lines from *.cpp and *.cl files (wants to remove extra space between if and for statement) -
for (* .....)
with
for(* .....)
and also
if (* .....)
with
if(* .....)
Can any one suggest me the grep command to do search and replace for all files.
Edited:
I tried with below commands:
sed -i 's/for (/for(/g' *.cpp
But got error like below:
sed: can't read *.cpp: No such file or directory
I think you need sed command (stream editor, see man sed on your mashine). It is more suitable for file editing.
sed -i -E 's/(for|if)[ ]+(\(.*\))/\1\2/g'
Let me explain:
-i stands for inline, that means that all changes will be done and saved in the file
-E is needed to use extended regular expression inside with sed
s/(for|if)[ ]+(\(.*\))/\1\2/g
s stands for substitute
/ is a separator, which separates different parts of command. Between first / and second / there is pattern that you need to find (and then replace). After second / and third / there that we want to have after substitution.
g in the end stands for global, that means to make changes in the whole file.
How to apply to every file that you need?
This question is already exist, so in the end you need to run in directory where are your files stored following command
find ./ -type f -exec sed -i -E 's/(for|if)[ ]+(\(.*\))/\1\2/g' {} \;
I hope, this will help:)
I have created the file "brol.txt", with following content:
for (correct
for(wrong
if (correct
if(wrong
I have launched following grep command:
grep -E "for \(|if \(" brol.txt
With following result:
for (correct
if (correct
Explanation:
grep -E means extended grep (allows to search for expression1 OR expression2,
separated by a pipe character)
\( means the search for a round bracket. The backslash is an escape character.

Sed * only modifying first file

I would like to delete the first 40 lines of a good number of ASCII files and save the ASCII files without those 40 lines
I'm working under OSX High Sierra, realized that the -i option in sed was not working unless I create a backup file, so I tried using this command:
sed -i'backup' -e '1,40d' *.txt
It however only modifies and deletes the first 40 lines in my first file (alphabetically), but not the others.
How can I edit multiple files with just one command?
Thanks
You can use the following command that will
look in the current folder
ignore sub folder
take only into account files whose filenames end with '*.txt'
before executing the sed command.
Command:
find . -maxdepth 1 -type f -name '*.txt' -exec sed -i 'backup' -e '1,40d' {} \;

sed extra characters at end of l command

I am trying replace value in a config file with sed in cshell.
However it gives me the error:
sed: 1: "/usr/local/etc/raddb/mo ...": extra characters at the end of l command
I am trying the following command:
sed -i "s/private_key_password = .*/private_key_password = test/" /usr/local/etc/raddb/mods-available/eap
I have looked at examples of sed to do this but they all look similar with what I am doing, what is going wrong here?
FreeBSD sed requires an argument after -i to rename the original file to. For example sed -i .orig 's/../../' file will rename he original file to file.orig, and save the modified file to file.
This is different from GNU sed, which doesn't require an argument for the -i flag. See sed(1) for the full documentation. This is one of those useful extensions to the POSIX spec which is unfortunately implemented inconsistently.
Right now, the "s/private_key_password = .*/private_key_password = test/" parts gets interpreted as an argument to -i, and /usr/local/etc/raddb/mods-available/eap gets interpreted as the command. Hence the error.
So you want to use:
sed -i .orig "s/private_key_password = .*/private_key_password = test/" /usr/local/etc/raddb/mods-available/eap
You can then check if the changes are okay with diff and remove /usr/local/etc/raddb/mods-available/eap.orig if they are.

Extracting the contents between two different strings using bash or perl

I have tried to scan through the other posts in stack overflow for this, but couldn't get my code work, hence I am posting a new question.
Below is the content of file temp.
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/<env:Body><dp:response xmlns:dp="http://www.datapower.com/schemas/management"><dp:timestamp>2015-01-
22T13:38:04Z</dp:timestamp><dp:file name="temporary://test.txt">XJzLXJlc3VsdHMtYWN0aW9uX18i</dp:file><dp:file name="temporary://test1.txt">lc3VsdHMtYWN0aW9uX18i</dp:file></dp:response></env:Body></env:Envelope>
This file contains the base64 encoded contents of two files names test.txt and test1.txt. I want to extract the base64 encoded content of each file to seperate files test.txt and text1.txt respectively.
To achieve this, I have to remove the xml tags around the base64 contents. I am trying below commands to achieve this. However, it is not working as expected.
sed -n '/test.txt"\>/,/\<\/dp:file\>/p' temp | perl -p -e 's#<dp:file name="temporary://test.txt">##g'|perl -p -e 's#</dp:file>##g' > test.txt
sed -n '/test1.txt"\>/,/\<\/dp:file\>/p' temp | perl -p -e 's#<dp:file name="temporary://test1.txt">##g'|perl -p -e 's#</dp:file></dp:response></env:Body></env:Envelope>##g' > test1.txt
Below command:
sed -n '/test.txt"\>/,/\<\/dp:file\>/p' temp | perl -p -e 's#<dp:file name="temporary://test.txt">##g'|perl -p -e 's#</dp:file>##g'
produces output:
XJzLXJlc3VsdHMtYWN0aW9uX18i
<dp:file name="temporary://test1.txt">lc3VsdHMtYWN0aW9uX18i</dp:response> </env:Body></env:Envelope>`
Howeveer, in the output I am expecting only first line XJzLXJlc3VsdHMtYWN0aW9uX18i. Where I am commiting mistake?
When i run below command, I am getting expected output:
sed -n '/test1.txt"\>/,/\<\/dp:file\>/p' temp | perl -p -e 's#<dp:file name="temporary://test1.txt">##g'|perl -p -e 's#</dp:file></dp:response></env:Body></env:Envelope>##g'
It produces below string
lc3VsdHMtYWN0aW9uX18i
I can then easily route this to test1.txt file.
UPDATE
I have edited the question by updating the source file content. The source file doesn't contain any newline character. The current solution will not work in that case, I have tried it and failed. wc -l temp must output to 1.
OS: solaris 10
Shell: bash
sed -n 's_<dp:file name="\([^"]*\)">\([^<]*\).*_\1 -> \2_p' temp
I add \1 -> to show link from file name to content but for content only, just remove this part
posix version so on GNU sed use --posix
assuming that base64 encoded contents is on the same line as the tag around (and not spread on several lines, that need some modification in this case)
Thanks to JID for full explaination below
How it works
sed -n
The -n means no printing so unless explicitly told to print, then there will be no output from sed
's_
This is to substitute the following regex using _ to separate regex from the replacement.
<dp:file name=
Regular text
"\([^"]*\)"
The brackets are a capture group and must be escaped unless the -r option is used( -r is not available on posix). Everything inside the brackets is captured. [^"]* means 0 or more occurrences of any character that is not a quote. So really this just captures anything between the two quotes.
>\([^<]*\)<
Again uses the capture group this time to capture everything between the > and <
.*
Everything else on the line
_\1 -> \2
This is the replacement, so replace everything in the regex before with the first capture group then a -> and then the second capture group.
_p
Means print the line
Resources
http://unixhelp.ed.ac.uk/CGI/man-cgi?sed
http://www.grymoire.com/Unix/Sed.html
/usr/xpg4/bin/sed works well here.
/usr/bin/sed is not working as expected in case if the file contains just 1 line.
below command works for a file containing only single line.
/usr/xpg4/bin/sed -n 's_<env:Envelope\(.*\)<dp:file name="temporary://BackUpDir/backupmanifest.xml">\([^>]*\)</dp:file>\(.*\)_\2_p' securebackup.xml 2>/dev/null
Without 2>/dev/null this sed command outputs the warning sed: Missing newline at end of file.
This because of the below reason:
Solaris default sed ignores the last line not to break existing scripts because a line was required to be terminated by a new line in the original Unix implementation.
GNU sed has a more relaxed behavior and the POSIX implementation accept the fact but outputs a warning.