Skip to content

Commit ba2fa40

Browse files
committed
tr command with flags
Translate or Delete Characters. Usage Pattern: tr [flags...] set1 [set2] Common Flags: -d: Delete characters in the first set. -s: Squeeze repeated characters occurring in the target set. -c: Complement the set of characters to be replaced.
1 parent db3b8c4 commit ba2fa40

File tree

2 files changed

+148
-2
lines changed

2 files changed

+148
-2
lines changed
Lines changed: 146 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,149 @@
11
package com.unixtools.command.filecontent;
22

3-
public class TrCommand {
4-
3+
import com.unixtools.core.Command;
4+
import java.io.BufferedReader;
5+
import java.io.IOException;
6+
import java.io.InputStreamReader;
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
10+
public class TrCommand implements Command {
11+
private static final String VALID_FLAGS = "dsc";
12+
private boolean deleteMode = false;
13+
private boolean squeezeMode = false;
14+
private boolean complementMode = false;
15+
private String set1;
16+
private String set2;
17+
18+
@Override
19+
public void execute(String[] args) {
20+
List<String> flags = new ArrayList<>();
21+
List<String> sets = new ArrayList<>();
22+
parseArguments(args, flags, sets);
23+
24+
if (!areFlagsValid(flags)) {
25+
System.out.println("Invalid flags. Valid flags are: " + VALID_FLAGS);
26+
return;
27+
}
28+
29+
if (deleteMode && sets.size() != 1) {
30+
System.out.println("tr: Exactly one set is required with delete mode.");
31+
return;
32+
}
33+
if (squeezeMode && sets.size() != 1) {
34+
System.out.println("tr: Exactly one set is required with squeeze mode.");
35+
return;
36+
}
37+
if (!deleteMode && !squeezeMode && sets.size() != 2) {
38+
System.out.println(
39+
"tr: Two sets are required for simple replacement without delete or squeeze mode.");
40+
return;
41+
}
42+
43+
set1 = expandSet(sets.get(0));
44+
set2 = sets.size() > 1 ? expandSet(sets.get(1)) : "";
45+
46+
try {
47+
processInput();
48+
} catch (IOException e) {
49+
System.err.println("Error processing input: " + e.getMessage());
50+
}
51+
}
52+
53+
private void parseArguments(String[] args, List<String> flags, List<String> sets) {
54+
for (String arg : args) {
55+
if (arg.startsWith("-")) {
56+
for (char flag : arg.substring(1).toCharArray()) {
57+
flags.add(String.valueOf(flag));
58+
switch (flag) {
59+
case 'd':
60+
deleteMode = true;
61+
break;
62+
case 's':
63+
squeezeMode = true;
64+
break;
65+
case 'c':
66+
complementMode = true;
67+
break;
68+
}
69+
}
70+
} else {
71+
sets.add(arg);
72+
}
73+
}
74+
}
75+
76+
private boolean areFlagsValid(List<String> flags) {
77+
return flags.stream().allMatch(flag -> VALID_FLAGS.contains(flag));
78+
}
79+
80+
private String expandSet(String set) {
81+
set = set.replace("[:alnum:]", "a-zA-zA-Z0-9")
82+
.replace("[:alpha:]", "a-zA-Z")
83+
.replace("[:digit:]", "0-9")
84+
.replace("[:lower:]", "a-z")
85+
.replace("[:upper:]", "A-Z")
86+
.replace("[:special:]", "!@#$%^&*()_+{}|:<>?[];',./`~\"");
87+
StringBuilder expandedSet = new StringBuilder();
88+
for (int i = 0; i < set.length(); i++) {
89+
if (i + 2 < set.length() && set.charAt(i + 1) == '-') {
90+
char start = set.charAt(i);
91+
char end = set.charAt(i + 2);
92+
for (char ch = start; ch <= end; ch++) {
93+
expandedSet.append(ch);
94+
}
95+
i += 2;
96+
} else {
97+
expandedSet.append(set.charAt(i));
98+
}
99+
}
100+
return expandedSet.toString();
101+
}
102+
103+
private void processInput() throws IOException {
104+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
105+
String line;
106+
while ((line = reader.readLine()) != null) {
107+
String processedLine = processLine(line);
108+
System.out.println(processedLine);
109+
}
110+
}
111+
}
112+
113+
private String processLine(String line) {
114+
StringBuilder result = new StringBuilder();
115+
char prevChar = '\0';
116+
117+
for (char ch : line.toCharArray()) {
118+
boolean inSet1 = set1.indexOf(ch) != -1;
119+
120+
if (deleteMode) {
121+
boolean shouldDelete = complementMode ? !inSet1 : inSet1;
122+
if (shouldDelete)
123+
continue;
124+
}
125+
126+
if (squeezeMode) {
127+
if (ch == prevChar && inSet1) {
128+
continue;
129+
}
130+
} else if (!deleteMode) {
131+
int index = set1.indexOf(ch);
132+
if (complementMode) {
133+
if (index == -1) {
134+
ch = set2.isEmpty() ? ch : set2.charAt(0);
135+
}
136+
} else {
137+
if (index != -1) {
138+
ch = (index < set2.length()) ? set2.charAt(index) : set2.charAt(set2.length() - 1);
139+
}
140+
}
141+
}
142+
143+
result.append(ch);
144+
prevChar = ch;
145+
}
146+
return result.toString();
147+
}
148+
5149
}

src/com/unixtools/core/CommandFactory.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ public static Command getCommand(String commandName) {
6464
return new UniqCommand();
6565
case "wc":
6666
return new WcCommand();
67+
case "tr":
68+
return new TrCommand();
6769
default:
6870
return null;
6971
}

0 commit comments

Comments
 (0)