Shell script to extract a filename from log message lines - bash

I have txt file which listed with some line. Each line has image names included. What I want is, The shell script that edit same txt file OR copy particular image name to new file.
This is my txt file having list of images with their paths.
And I want output like this:
I want only image names should be extract from those lines.

You can use this awk,
awk '{ split($1,arr,"/"); print arr[length(arr)] }' yourfile > output.txt

Using gnu sed you can do:
sed -r 's~^[^[:blank:]]*/([^/ ]+) .*$~\1~' file
1.png
1#2x.png
2.png
2#2x.png
3.png

You can do something like:
cat the_file.txt|while read file; do
echo $(basename $file)
done
And (if needed) redirect the output on another file.

while read fn rest
do
basename "$fn"
done < file.txt
This will read your input line by line. It will put the filename (including path) into the fn variable, and whatever is on the rest of the line into rest. Then it uses the basename command to strip off the path and just print out the filename itself.

This is another sed solution that doesn't use extended regular expression (more portable solution):
sed 's/^.*\/\([^[:blank:]\/]*\)[[:blank:]].*$/\1/' sourceFile > destFile
You have to replace sourceFile and destFile white the path to oridinal and destination file respectively.
The command look for any string without blank char or slashes \([^[:blank:]\/]*\) preceeded by a slash ^.*\/ and followed by a blank char [[:blank:]].*$ than the patter is substitituded with the first matching string /\1/.
You could read a quick sed reference here.

Related

Pipe last 11 characters in filename to a text file

Have a directory full of file names that end with .mp3 and have a code in it that i would like to pipe into a text file.
I need to get the last 11 characters before the .mp3 part of a file in a certain directory and pipe that into a text file (with bash on mac osx)
How do I accomplish this? With sed?
If I'm understanding correctly, you have a list of files with names like "abcdefghijklmnopqrstuvwxyz.mp3" and want to extract "pqrstuvwxyz". You can do this directly in bash without invoking any fancy sed business:
for F in *.mp3; do STRIP=${F/.mp3}; echo ${STRIP: -11}; done > list.txt
The first STRIP variable is the name of each file F with the .mp3 extension removed. Then you echo the last 11 characters and save to a file.
There's a nice page on bash substitutions here. sed is great but I personally find it's overkill for these simple cases.
Along with good above answers, can be done via awk
for f in `ls *.mp3`;
echo $f|awk -F. '{printf substr($1,length($1)-11,length($1)),$2;}'
done

Bash - Comment out a specific line that partly matches a string in a file

I have a file with an argument
testArgument=
It could have something equal to it or nothing but I want to comment it and add the new line with supplied info
Before:
testArgument=Something
Results:
#testVariable=Something
#Comments to let the user know of why the change
testVariable=NewSomething
Should I loop it or should I use something like sed? I need it to be compatible for Ubuntu and Debian and bash.
You could use sed like this:
sed 's/^\(testArgument\)=.*/#&\n\n#Comment here\n\1=NewSomething/' file
& prints the full match in the replacement and \1 refers to the first capture group "testArgument".
To perform the substitution on the file in-place (i.e. replace the contents of the original file), add the -i switch. Otherwise, if you want to output the command to a new file, do sed '...' file > newfile.
If you are using a different version of sed that doesn't support \n newlines in the replacement, see this answer for some ways to deal with it.
Alternatively, using GNU awk:
gawk '/^testArgument/ {$0 = gensub(/^(testArgument)=.*/, "#\\0\n\n#Comment here\n\\1=NewSomething", 1)}1' file
You can use awk
awk '/^testArugment/ {$0="#"$0"\n\n#Comments to let the user know of why the change\ntestVariable=NewSomething"}1' file
cat file
some data
testArugment=Something
more data
awk '/^testArugment/ {$0="#"$0"\n\n#Comments to let the user know of why the change\ntestVariable=NewSomething"}1' file
some data
#testArugment=Something
#Comments to let the user know of why the change
testVariable=NewSomething
more data
To change the original file
awk 'code....' file > tmp && mv tmp file

How to extract a string at end of line after a specific word

I have different location, but they all have a pattern:
some_text/some_text/some_text/log/some_text.text
All locations don't start with the same thing, and they don't have the same number of subdirectories, but I am interested in what comes after log/ only. I would like to extract the .text
edited question:
I have a lot of location:
/s/h/r/t/log/b.p
/t/j/u/f/e/log/k.h
/f/j/a/w/g/h/log/m.l
Just to show you that I don't know what they are, the user enters these location, so I have no idea what the user enters. The only I know is that it always contains log/ followed by the name of the file.
I would like to extract the type of the file, whatever string comes after the dot
THe only i know is that it always contains log/ followed by the name
of the file.
I would like to extract the type of the file, whatever string comes
after the dot
based on this requirement, this line works:
grep -o '[^.]*$' file
for your example, it outputs:
text
You can use bash built-in string operations. The example below will extract everything after the last dot from the input string.
$ var="some_text/some_text/some_text/log/some_text.text"
$ echo "${var##*.}"
text
Alternatively, use sed:
$ sed 's/.*\.//' <<< "$var"
text
Not the cleanest way, but this will work
sed -e "s/.*log\///" | sed -e "s/\..*//"
This is the sed patterns for it anyway, not sure if you have that string in a variable, or if you're reading from a file etc.
You could also grab that text and store in a sed register for later substitution etc. All depends on exactly what you are trying to do.
Using awk
awk -F'.' '{print $NF}' file
Using sed
sed 's/.*\.//' file
Running from the root of this structure:
/s/h/r/t/log/b.p
/t/j/u/f/e/log/k.h
/f/j/a/w/g/h/log/m.l
This seems to work, you can skip the echo command if you really just want the file types with no record of where they came from.
$ for DIR in *; do
> echo -n "$DIR "
> find $DIR -path "*/log/*" -exec basename {} \; | sed 's/.*\.//'
> done
f l
s p
t h

Script for removing the words in the line

Is there any script for removing the words in the line for example these:
"my_name/your_name/ours_name/name"
"my_name/name"
I want to remove the words within the double quotes and before the last slash. Whatever the word appear, I need to remove it. After removing, both of them should be:
"name"
To be more specific: I have one folder, in that folder there are multiple files. Each file consists of a header file like #include "my_name/ur_name/name". I want it to be #include "name", because I want to make that header in the current directory.
you can try the below command,
Commmand:
sed -i 's|#include "my_name/ur_name/name"|#include "name"|g' *
Description:
command will replace (#include "my_name/ur_name/name") with (#include "name") into all the files of directory
NOTE:
Command immediately returns "OK" message,But it will take time to perform the internal file operations.
Shell file
Create a file called main.sh and copy this:
#Get parameter.
string=$1
#Explode string to array.
IFS='/' read -a array <<< "$string"
#Get array size.
size=${#array[#]}
#Get last array element.
echo ${array[$size-1]}
BASH usage
Now you can call main.sh with the path between double quotes as a parameter and it will return the last segment.
$bash -f main.sh "my_name/your_name/ours_name/name"
name
$bash -f main.sh "my_name/name"
name
Maybe you should also look at this question: Take the last part of the folder path in shell
A Simple one line will do this
file.txt
"my_name/your_name/ours_name/name"
"my_name/x_name"
Command
sed 's/^"//g' file.txt | awk 'BEGIN {FS="/"} {print $NF}' | sed 's/^/"/g'
Output
"name"
"x_name"

How to append to specific lines in a flat file using shell script

I have a flat file that contains something like this:
11|30646|654387|020751520
11|23861|876521|018277154
11|30645|765418|016658304
Using shell script, I would like to append a string to certain lines in this file, if those lines contain a specific string.
For example, in the above file, for lines containing 23861, I would like to append a string "Processed" at the end, so that the file becomes:
11|30646|654387|020751520
11|23861|876521|018277154|Processed
11|30645|765418|016658304
I could use sed to append the string to all lines in the file, but how do I do it for specific lines ?
I'd do it this way
sed '/\|23861\|/{s/$/|Something/;}' file
This is similar to Marcelo's answer but doesn't require extended expressions and is, I think, a little cleaner.
First, match lines having 23861 between pipes
/\|23861\|/
Then, on those lines, replace the end-of-line with the string |Something
{s/$/|Something/;}
If you want to do more than one of these you could simply list them
sed '/\|23861\|/{s/$/|Something/;};/\|30645\|/{s/$/|SomethingElse/;}' file
Use the following awk-script:
$ awk '/23861/ { $0=$0 "|Processed" } {print}' input
11|30646|654387|020751520
11|23861|876521|018277154|Processed
11|30645|765418|016658304
or, using sed:
$ sed 's/\(.*23861.*$\)/\1|Processed/' input
11|30646|654387|020751520
11|23861|876521|018277154|Processed
11|30645|765418|016658304
Use the substitution command:
sed -i~ -E 's/(\|23861\|.*)/\1|Processed/' flat.file
(Note: the -i~ performs the substitution in-place. Just leave it out if you don't want to modify the original file.)
You can use the shell
while read -r line
do
case "$line" in
*23681*) line="$line|Processed";;
esac
echo "$line"
done < file > tempo && mv tempo file
sed is just a stream version of ed, which has a similar command set but was designed to edit files in place (allegedly interactively, but you wouldn't want to use it that way unless all you had was one of these). Something like
field_2_value=23861
appended_text='|processed'
line_match_regex="^[^|]*|$field_2_value|"
ed "$file" <<EOF
g/$line_match_regex/s/$/$appended_text/
wq
EOF
should get you there.
Note that the $ in .../s/$/... is not expanded by the shell, as are $line_match_regex and $appended_text, because there's no such thing as $/ - instead it's passed through as-is to ed, which interprets it as text to substitute ($ being regex-speak for "end of line").
The syntax to do the same job in sed, should you ever want to do this to a stream rather than a file in place, is very similar except that you don't need the leading g before the regex address:
sed -e "/$line_match_regex/s/$/$appended_text/" "$input_file" >"$output_file"
You need to be sure that the values you put in field_2_value and appended_text never contain slashes, because ed's g and s commands use those for delimiters.
If they might do, and you're using bash or some other shell that allows ${name//search/replace} parameter expansion syntax, you could fix them up on the fly by substituting \/ for every / during expansion of those variables. Because bash also uses / as a substitution delimiter and also uses \ as a character escape, this ends up looking horrible:
appended_text='|n/a'
ed "$file" <<EOF
g/${line_match_regex//\//\\/}/s/$/${appended_text//\//\\/}/
wq
EOF
but it does work. Nnote that both ed and sed require a trailing / after the replacement text in s/search/replace/ while bash's ${name//search/replace} syntax doesn't.

Resources